摘 要: 分析了MVC描述的軟件模型,通過一個基于PHP語言并結(jié)合XML和XSL技術(shù)的MVC架構(gòu)的設(shè)計實例討論了MVC模式設(shè)計的方法。
關(guān)鍵詞: MVC架構(gòu) 控制器 視圖 模型
1 MVC描述的軟件模型
MVC是Model-View-Controller(模型-視圖-控制器)的縮寫,,它把一個應(yīng)用的處理流程分成模型層,、視圖層和控制層,,這三層結(jié)構(gòu)之間的關(guān)系如圖1所示,。
模型層(也稱業(yè)務(wù)層)用于處理程序邏輯。它的任務(wù)是管理應(yīng)用程序域的行為和數(shù)據(jù),,響應(yīng)來自控制層的狀態(tài)指令,,把原有數(shù)據(jù)按照業(yè)務(wù)邏輯轉(zhuǎn)換成指定意義的數(shù)據(jù)提供給視圖層顯示。
視圖層用于把表示模型數(shù)據(jù),、邏輯關(guān)系和狀態(tài)的信息以特定的形式表現(xiàn)在用戶界面上,。視圖層的顯示信息來自模型層,同一個模型可以對應(yīng)多個視圖,。
控制層用于處理用戶與軟件的交互操作,。控制層通知模型和視圖做出相應(yīng)的狀態(tài)改變,,使模型和視圖協(xié)調(diào)工作,。
2 MVC模式設(shè)計
MVC的目的是增加代碼的重用率,減少數(shù)據(jù)表達,、數(shù)據(jù)描述和應(yīng)用操作的耦合度,,從而提高軟件的可維護性、擴展性和靈活性,。MVC模式把界面表現(xiàn)和邏輯控制語句強制分離,,解決了頁面設(shè)計和程序開發(fā)中的工作交錯與沖突,并解決了由于商業(yè)邏輯嵌入造成程序不可重用而且很難維護的問題,。
本文設(shè)計了一個基于PHP語言,、XML和XSL模板技術(shù)的MVC架構(gòu)的Web應(yīng)用系統(tǒng),。
2.1 代碼結(jié)構(gòu)
在系統(tǒng)中每一個頁面被定義為一個Action,可以通過網(wǎng)址http://servername/index.php,?action=actionname來訪問頁面,。控制器中定義了每一個Action對應(yīng)的模型和視圖,,它們之間的對應(yīng)關(guān)系如圖2所示,。
表1為系統(tǒng)的基礎(chǔ)代碼結(jié)構(gòu),,除少量的靜態(tài)頁面放在htdocs目錄下外,,其余的程序都放在PHP的庫文件目錄下。
在這個代碼結(jié)構(gòu)中,,模型,、視圖和控制器三部分分別放置在不同目錄中。其中,,視圖層包括顯示模板(XSL)和頁面操作控制(JS)二部分,,模型層包括業(yè)務(wù)邏輯處理類庫(Action Class)、數(shù)據(jù)輸出處理(Action Execute)和PHP基礎(chǔ)類庫(PHP Class)三部分,。因此,,在系統(tǒng)中各部分的開發(fā)由不同的角色來完成,角色之間的工作交錯和沖突可以減少,,使系統(tǒng)程序升級和維護的思路也更加明晰,。
2.2 系統(tǒng)實現(xiàn)
在系統(tǒng)中,客戶端瀏覽器中呈現(xiàn)的是系統(tǒng)的視圖部分,,而模型和控制器則是透明的,。當(dāng)Web 服務(wù)器接收到客戶提交的HTTP請求后,交給服務(wù)器中的控制器來處理,??刂破靼凑照埱笾械腁ction信息,從系統(tǒng)配置中提取此Action的映射表,,并把此請求映射到相應(yīng)的處理模型,;處理模型進行業(yè)務(wù)邏輯處理,處理完后返回狀態(tài)更新的請求并將XML格式的數(shù)據(jù)結(jié)果給控制器,;控制器根據(jù)結(jié)果選擇相應(yīng)視圖模板并合成視圖返回給客戶,。程序架構(gòu)如圖3所示。
2.2.1 控制層的實現(xiàn)
在這個系統(tǒng)中,,控制器主要有以下四個作用,。
(1)根據(jù)Action名稱從數(shù)據(jù)庫的映射表中找到處理此Action的模型信息、視圖模板和此視圖的用戶操作控制信息,。
(2)調(diào)用模型處理Action請求,。
(3)合成業(yè)務(wù)邏輯處理返回的XML格式的數(shù)據(jù)信息和XSL視圖模板為HTML的文件,,并返回給客戶端。
(4)在接收到一個業(yè)務(wù)邏輯處理模型返回的狀態(tài)更新請求后,,調(diào)用一個新的業(yè)務(wù)邏輯處理模型處理此請求,。
控制器主要包括二個文件:includes/prepend.inc和includes/controller/controller.inc。prepend.inc文件被設(shè)定為自動增加在被訪問的文件前,,因此這個文件非常適合作為控制器的主文件,;Controller.inc中主要是控制器中的處理函數(shù)。這二個文件的代碼如下,。
prepend.inc
<?
include_once(″/action/configure/db.conf″),;//數(shù)據(jù)庫連接對象
include_once(″/control/controller.inc″);//控制器
…
$actionobj=getaction($action),; //獲得Action信息
if($actionobj[″model″] !=″″){
//調(diào)用model處理action請求信息
include_once($actionobj[″model″]),;
eval(″\$modelobj=execute_″.$actionobj[″action″].″( );″),;
if($modelobj[″type″]==″xmldata″){//返回html
//輸出xml和xsl合成的html數(shù)據(jù)
echo xmlpraser($modelobj[″data″],,$actionobj[″view″]);
}else if($modelobj[″type″]==″state″){ //請求更新狀態(tài)
header(″Location:?″.$modelobj[″data″]),; //交新模型處理
exit,;
}
}else{//直接調(diào)用View輸出}
?>
controller.inc:
<?
****得actionobj的信息****
function getaction($action){
global $dbobj,$conn,,$result_id,; //數(shù)據(jù)對象,連接,,結(jié)果集
//從數(shù)據(jù)庫中檢索action對象信息
$sqlstr=″select*from t_action where action=′″.$action.″′″,;
$result_id=$dbobj->exec($conn,$sqlstr),;
if($dbobj->fetch_row($result_id)){
$actobj[″action″]=$action,;
//action的處理模型名稱
$actobj[″model″]=$dbobj->result($result_id,″model″),;
//action的視圖模板信息
$actobj[″view″]=$dbobj->result($result_id,,″template″);
//其他控制參數(shù)
}else{ … }
return $actobj,;
}
//****解析xml和xslt****
function php_scheme_get_all($Processor,,$Schema,$RestUri){
$url=$Schema .′:′. $RestUri,;
return file_get_contents($url),;
}
function xmlpraser($data,$xslpath){
global $SYS_INCLUDEPATH,;
$parser=xslt_create( ),; //初始化解析對象
xslt_set_scheme_handlers($parser,,array(′get_all′=>
′php_sheme_get_all′)); //設(shè)置處理方式
$parms[″_xml″]=″<?xml version=\″1.0\″ encoding=\″gb2312\
″?>″ . $data,; //合成xml格式數(shù)據(jù)
$parms[″_xsl″]=file_get_contents($SYS_INCLUDEPATH.
″\\″ . $xslpath),; //讀取xsl模板文件
$result.=xslt_process($parser,′arg:/_xml′,,′arg:/_xsl′,,
NULL,$parms),; //合成視圖
xslt_free($parser),; //釋放解析對象
return $result;
}
?>
2.2.2 模型層的實現(xiàn)
模型是系統(tǒng)的數(shù)據(jù)核心,。此系統(tǒng)中模型層主要包括三部分內(nèi)容,。
(1)業(yè)務(wù)邏輯處理。業(yè)務(wù)邏輯處理又可以分為二類:一類是抽象出來的業(yè)務(wù)邏輯,,被封裝成一個個PHP類;另一類是對某一具體Action的邏輯處理,。
(2)PHP的基礎(chǔ)類庫,。此部分與業(yè)務(wù)邏輯無關(guān),描述的是對任何一類的應(yīng)用系統(tǒng)中都要使用的公共函數(shù)類,,這些類可以被其他程序調(diào)用,。
(3)數(shù)據(jù)輸出處理,把PHP數(shù)據(jù)轉(zhuǎn)換成XML格式輸出,。
按照控制器的定義,,每一個Actionname都要調(diào)用一個命名為execute_actionname( )的函數(shù),這個函數(shù)會返回Action的處理結(jié)果,。處理結(jié)果有二種情況:一種是返回XML格式的數(shù)據(jù),;一種是返回要求系統(tǒng)更新狀態(tài)的狀態(tài)值。一個典型的模型處理器程序結(jié)構(gòu)如下:
<?
include_once(″/action/tool/tools.inc″),; //工具系統(tǒng)的基礎(chǔ)類
function gettoollist($toolid){ //獲得工具信息
//指定要獲得的工具信息
$params=array(″toolname″,,″part_no″,″quantity″),;
$toolobj=new toolinfo,; //創(chuàng)建toolinfo類實例
$toolstinfo=$toolobj->GetToolListinfo($toolid,$params),;
return $toolsinfo,; //返回工具列表信息
}
function getxml($toolsinfo){ //轉(zhuǎn)換工具信息為xml格式
while(list($id,$toolarray)=each($toolsinfo[″data″])){
$xmlstr.=″<items>″,;
while(list($key,,$value)=each($toolarray)){
$xmlstr.=″<″ .$key. ″>″.$value.″</″.$key.″>″,;
}
$xmlstr.=″</items>″;
}
return $xmlstr,;
}
function execute_tool_toollist( ) { //工具列表action的處理函數(shù)
$toolinfo=gettoollist($toolid),; //工具信息
if($toolinfo[″state″]){ //輸出xml格式數(shù)據(jù)
$rtnobj[″type″]=″xmldata″;
$rtnobj[″data″]=getxml(($toolinfo),;
}else{ //跳轉(zhuǎn)到錯誤處理頁面
$rtnobj[″type″]=″state″,;
$rtnobj[″data″]=″errorhandle″;
}
return $rtnobj,;
}
?>
2.2.3 視圖層的實現(xiàn)
視圖是系統(tǒng)與客戶交互的窗口,。在Web應(yīng)用系統(tǒng)中,視圖是指客戶最終看到的HTML頁面,。為了使頁面具有風(fēng)格統(tǒng)一,、整齊、可配置的特點,,系統(tǒng)一般都會采用模板技術(shù),。此系統(tǒng)即使用了XSL模板技術(shù)。系統(tǒng)中的視圖層包括二部分:一部分是放在/includes/template目錄下的XSL模板,;另一部分是放在/htdocs目錄下的js和css文件,。最后,由控制器來完成合成視圖的任務(wù),。
2.3 系統(tǒng)適應(yīng)性
從整個系統(tǒng)的設(shè)計結(jié)構(gòu)可以看出,,系統(tǒng)的業(yè)務(wù)邏輯和顯示是分離的:首先由網(wǎng)頁設(shè)計人員和程序員共同確定需要的數(shù)據(jù)項和Action名稱,在控制器中添加此Action,;之后,,網(wǎng)頁設(shè)計人員設(shè)計各個顯示模板;程序人員完成相應(yīng)的模型處理程序,。這樣的設(shè)計方法有利于對系統(tǒng)的維護和功能擴展,。
在MVC系統(tǒng)中處理用戶需求的思路非常明確。視圖的修改和模型處理的修改基本上是獨立的,,無論是在系統(tǒng)開發(fā)時期還是在系統(tǒng)維護時期,,網(wǎng)頁設(shè)計人員和程序員都可以更加專注于自己的任務(wù)。系統(tǒng)中的模型可以是自包含的,,由于與控制器和視圖相分離,,所以很容易改變程序的數(shù)據(jù)層和業(yè)務(wù)規(guī)則。例如把數(shù)據(jù)庫從Mysql移植到Oracle上只需改變數(shù)據(jù)庫連接模型即可,;而把界面顯示從HTML改為Flash或WAP只需改變視圖顯示和相應(yīng)控制器即可,。一旦正確地實現(xiàn)了模型,視圖將會正確地加以顯示,。這樣,,系統(tǒng)維護的成本和項目的開發(fā)風(fēng)險都被大大降低,。
3 結(jié)束語
MVC設(shè)計思想中的三部分是相互獨立的,既可以通過不同的技術(shù)實現(xiàn),,也可以運行在不同的基礎(chǔ)平臺上,。隨著更多新技術(shù)的出現(xiàn),還可以創(chuàng)造出更多的應(yīng)用方式,。所以MVC設(shè)計模式的確是一個創(chuàng)建優(yōu)秀軟件的途徑,。
本文所描述的只是MVC應(yīng)用系統(tǒng)開發(fā)的一個基礎(chǔ)模式。模型和視圖嚴(yán)格分離的模式相對混合模式,,對開發(fā)和設(shè)計人員的要求要高一些,,但更容易進行錯誤控制。此外,,在實際的應(yīng)用中,,開發(fā)者還要結(jié)合各應(yīng)用項目的業(yè)務(wù)需要進行詳細的設(shè)計規(guī)劃,認真考慮應(yīng)用的額外復(fù)雜性,。只有把這些想法融進到架構(gòu)中,,才能增加應(yīng)用的可拓展性。只有把握這一點,,MVC模式才會使得應(yīng)用系統(tǒng)更加健壯,、更加靈活和更容易擴展。
參考文獻
1 Kotek B.MVC design pattern brings about better organisation and code reuse.http://builder.com.com/5100-6386-1049862.html,,2002
2 龔赤兵.如何合理利用MVC設(shè)計模式運用到開發(fā)Java應(yīng) 用程序.http://tech.163.com/tm/030622/ 030622_99290. html,2003
3 Gamma E著,,李英軍譯.設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ).北京:機械工業(yè)出版社,,2000