楊毅
摘要:程序開發(fā)框架的選擇,始終是個仁者見仁、智者見智的事情。尤其是WEB層的開發(fā)框架,數(shù)量非常多,而且各有特色,常見的有MVC、MVP、AOP、ORM、MVVM等,文章將主要對MVC、MVP、MVVM三種框架進(jìn)行分析,敘述其優(yōu)缺點,以方便開發(fā)人員進(jìn)行選擇。
關(guān)鍵詞:MVC;MVP;MVVM
1MVC框架
MVC(Model View Controller)是把軟件系統(tǒng)分為模型、視圖、控制器3個基本部分。M是指數(shù)據(jù)模型,V是指用戶界面,c則是控制器。使用MVC的目的是將M和V的實現(xiàn)代碼分離,從而使同一個程序可以使用不同的表現(xiàn)形式。比如一批統(tǒng)計數(shù)據(jù)可以分別用柱狀圖、餅圖來表示。C存在的目的則是確保M和V的同步,一旦M改變,V應(yīng)該同步更新。
圖1為Java實現(xiàn)的MVC模型,Java MVC模式是將Servlet,Jsp和JavaBean結(jié)合起來的技術(shù)。Servlet適合數(shù)據(jù)處理,JavaBean用于模型,而Jsp適合顯示。這個模式充分發(fā)揮了每項技術(shù)的優(yōu)點。
在早期的WEB開發(fā)中,因為業(yè)務(wù)比較簡單,并沒有這3層的劃分。用戶數(shù)據(jù)的呈現(xiàn)及輸入的接收、封裝、驗證、處理、以及對數(shù)據(jù)庫的操作,都放在Jsp頁面中。隨著業(yè)務(wù)越來越復(fù)雜,需要考慮更好的利用OOP來解決問題。于是便把業(yè)務(wù)邏輯抽取出來并形成與顯示和持久化無關(guān)的一層,能夠讓業(yè)務(wù)邏輯清晰,產(chǎn)品更便于維護(hù)。這就是SUN當(dāng)初倡導(dǎo)的JSP Model1開發(fā)方式。
Modell模式的實現(xiàn)比較簡單,適用于快速開發(fā)小規(guī)模項目。但從工程化的角度看,局限性非常明顯:JSP頁面身兼View和Controller2種角色,將控制邏輯和表現(xiàn)邏輯混雜在一起,從而導(dǎo)致代碼的重用性非常低,增加了應(yīng)用的擴(kuò)展性和維護(hù)的難度。
Jsp Model2中引入了MVC框架,使用了3種技術(shù)JSP、Servlet和JavaBeans,Jsp負(fù)責(zé)生成動態(tài)網(wǎng)頁,只用做顯示頁面。Servlet負(fù)責(zé)流程控制,用來處理各種請求的分派。JavaBeans負(fù)責(zé)業(yè)務(wù)邏輯,對數(shù)據(jù)庫的操作。
大部分Web應(yīng)用程序都是用像ASP,PHP,或者JSP來創(chuàng)建的。造成了數(shù)據(jù)庫查詢語句這樣的數(shù)據(jù)層代碼和像HTML這樣的表示層代碼混在一起。由經(jīng)驗的開發(fā)者會將數(shù)據(jù)從表示層分離開來,交由后臺處理,但這通常不是很容易做到的,它需要精心的計劃和不斷的嘗試。而使用MVC框架,應(yīng)用程序被分成3個核心部件:模型、視圖、控制器,各自處理自己的任務(wù)。盡管使用MVC框架需要付出一些額外的工作,但是給人們帶來的好處是無庸質(zhì)疑的。
視圖(View)代表用戶交互界面,通常由網(wǎng)頁組成。在早期WEB開發(fā)中,網(wǎng)頁的數(shù)據(jù)嵌入在頁面中,無論頁面打開多少次,頁面內(nèi)容也不會發(fā)生變化,這種頁面稱為靜態(tài)網(wǎng)頁。而MVC框架中View視圖中的數(shù)據(jù)來源于數(shù)據(jù)庫,隨著數(shù)據(jù)庫數(shù)據(jù)的變化,頁面中的數(shù)據(jù)也會隨著發(fā)生改變,稱之為動態(tài)網(wǎng)頁,現(xiàn)在比較流行的動態(tài)網(wǎng)頁開發(fā)技術(shù)由Jsp、Asp和Php。Java的MVC模型就是采用的Jsp動態(tài)開發(fā)技術(shù),因此View的頁面由jsp網(wǎng)頁組成。在View層只涉及數(shù)據(jù)的顯示,和數(shù)據(jù)的采集,不涉及視圖的業(yè)務(wù)處理。比如最常見的登錄頁面,登錄視圖只是把登錄的信息進(jìn)行收集并提交,不對登錄的信息做判斷。
模型(Model):就是業(yè)務(wù)流程/狀態(tài)的處理以及業(yè)務(wù)規(guī)則的制定。在MVC的3個部件中,模型擁有最多的處理任務(wù)。視圖中的數(shù)據(jù)由Model來提供,當(dāng)需要改變視圖中的數(shù)據(jù)時,不需要修改WEB頁面,只需要修改相應(yīng)的Model即可。MVC框架中Model層的主要關(guān)注點是如何把請求的數(shù)據(jù)自動裝配成Action所需要的bean,除此外,框架Model層還可以提供復(fù)合bean自動裝配、輸入校驗、本地化及國際化、字符集編碼轉(zhuǎn)換、多重輸出等功能。比如上述的登錄系統(tǒng),就是由Model層來完成登錄賬號和密碼的判定。由于應(yīng)用于模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復(fù)性。
控制(Controller)接受用戶的輸入并調(diào)用模型和視圖去完成用戶的需求。Java MVC中的控制層由Servlet來實現(xiàn)??刂茖硬⒉粚?shù)據(jù)做處理,而是根據(jù)視圖的提交要球,來決定調(diào)用相對應(yīng)的模型。比如上述的登錄系統(tǒng),控制器的作用就是接收View層提交的信息,并把這個信息傳給對應(yīng)的Model去處理,然后把處理后的結(jié)果,再返回給View層。
MVC的優(yōu)點:(1)可以為一個模型在運行時同時建立和使用多個視圖。變化-傳播機(jī)制可以確保所有相關(guān)的視圖及時得到模型數(shù)據(jù)變化,從而使所有關(guān)聯(lián)的視圖和控制器做到行為同步。(2)視圖與控制器的可接插性,允許更換視圖和控制器對象,而且可以根據(jù)需求動態(tài)的打開或關(guān)閉、甚至在運行期間進(jìn)行對象替換。(3)模型的可移植性。因為模型是獨立于視圖的,所以可以把一個模型獨立地移植到新的平臺工作。需要做的只是在新平臺上對視圖和控制器進(jìn)行新的修改。(4)潛在的框架結(jié)構(gòu)??梢曰诖四P徒?yīng)用程序框架,不僅僅是用在設(shè)計界面的設(shè)計中。
MVC的不足體現(xiàn)在以下幾個方面:(1)MVC并沒有很明確的定義,所以完全理解MVC并不是很容易。并且內(nèi)部實現(xiàn)原理比較復(fù)雜和多樣,對于新手來說需要花費一些時間去思考。(2)視圖與控制器的可接插性,造成模型和視圖的分離,這樣也給調(diào)試應(yīng)用程序帶來了一定的困難。(3)MVC的實現(xiàn)比較復(fù)雜,并不適合小型甚至中等規(guī)模的應(yīng)用程序,花費大量時間將MVC應(yīng)用到規(guī)模并不是很大的應(yīng)用程序通常會得不償失。
2MVP框架
MVC(Model-View-Controller,模型-視圖-控制器)模式是80年代Smalltalk-80出現(xiàn)的一種軟件設(shè)計模式,后來得到了廣泛的應(yīng)用,其主要目的在于促進(jìn)應(yīng)用中模型、視圖、控制器間的關(guān)注的清晰分離。MVP(Model-View-Presenter,模型視圖-表示器)模式則是由IBM開發(fā)出來的一個針對C++和Java的編程模型,大概出現(xiàn)于2000年,是MVC模式的一個變種,主要用來隔離UI、UI邏輯和業(yè)務(wù)邏輯、數(shù)據(jù)。
Model-View-Presenter旨在應(yīng)用程序分層和提高測試效率,主要目標(biāo)是將顯示邏輯與業(yè)務(wù)邏輯分離,正如設(shè)計面向?qū)ο蟪绦蛑袆?chuàng)建松散耦合并可重用的對象。MVP的另一個目標(biāo)是提高針對View的測試效率。編寫依賴Session,ViewState,AJAX,HTML或web控件和業(yè)務(wù)實體的單元測試類較為復(fù)雜,因此將各視圖的顯示邏輯保留在ASPX/ASCX文件類中,并將業(yè)務(wù)邏輯從中分離出來放在相應(yīng)的類中,在MVP中Presenter充當(dāng)視圖和業(yè)務(wù)邏輯的緩沖層。
MVC和MVP的區(qū)別:在MVP里,Presenter把Model層和View層進(jìn)行了完全的分離,View并不直接使用Model,主要的業(yè)務(wù)邏輯在Presenter里實現(xiàn)。而且,Presenter與具體的View是沒有直接關(guān)聯(lián)的,而是通過定義好的接口進(jìn)行交互,從而使得在變更View時候可以保持Presenter的不變,達(dá)到了重用的效果,而在MVC中View會從直接Model中讀取數(shù)據(jù)而不是通過Controlle如圖2所示。
從圖中可以看到,在MVC里,View是可以直接訪問Model的,View里會包含Model信息,因此不可避免的還要包括一些業(yè)務(wù)邏輯。在MVC模型里,更注重業(yè)務(wù)的邏輯,也就是Model的不變,而針對Model,則有不同的顯示及View。所以,在MVC模型里,View是依賴于Model的,但是Model不依賴于View。并且,如果有一些業(yè)務(wù)邏輯在View里實現(xiàn)了,則導(dǎo)致要更改View也是比較困難的,因為View中的業(yè)務(wù)邏輯是無法重用的。
在MVP模式里,View只有簡單的Set/Get的方法,用來輸入和設(shè)置界面顯示的內(nèi)容,除此就不應(yīng)該有更多的內(nèi)容,絕不容許直接直接訪問Model,而這就是與MVC很大的不同之處。
MVP的優(yōu)點:(1)View和Model實現(xiàn)了完全分離,可以修改View而不影響Model。(2)業(yè)務(wù)邏輯的處理更加集中,便于控制。(3)多個View可以共用一個Presener,便于代碼的重用。(4)業(yè)務(wù)邏輯集中在Presenter中,便于進(jìn)行單元測試。
MVP的缺點:由于對View的控制放在了Presenter中,造成了View和Persenter的交互會過于頻繁。這樣會增加View和Presenter的耦合性,一旦View發(fā)生了變化,Presenter也需要進(jìn)行變化。比如,原來的Html網(wǎng)頁顯示的是Word文檔,但是新求需要將Word文檔轉(zhuǎn)換為PDF文檔顯示,那么就需要更改View和Presenter。
3MVVM框架
MVVM是3層架構(gòu),M層(Model實體層)、V層(View表示層)、VM層(ViewModel層,對Model層進(jìn)行CRUD進(jìn)行操作,同時對V層提供數(shù)據(jù)綁定)。對這種模式的實現(xiàn),大部分都是通過在view層聲明數(shù)據(jù)綁定來和其他層分離的,這樣就方便了前端開發(fā)人員和后端開發(fā)人員的分工,前端開發(fā)人員在html標(biāo)簽中寫對Viewmodel的綁定數(shù)據(jù),Model和Viewmodel是后端開發(fā)人員通過開發(fā)應(yīng)用的邏輯來維護(hù)這兩層。
最近幾年,MVVM模式在Javascript中開始有人實現(xiàn),目前比較成熟的框架有KnockoutJS,Avalon MVVM和Knockback.js,原理如圖3所示。
(1)infoChannel:信息通道,主要用于向后臺發(fā)起數(shù)據(jù)請求。(2)dataChannel:數(shù)據(jù)通道,主要用于存儲從后臺獲取到的數(shù)據(jù)。(3)moleManage:數(shù)據(jù)操作,主要用于操作數(shù)據(jù)通道中的數(shù)據(jù),如crud操作。(4)modulePool:數(shù)據(jù)倉庫,主要存儲后臺返回的數(shù)據(jù)。(5)crudStorePool:crud實例池,增刪改的數(shù)據(jù),在持久化到數(shù)據(jù)庫之前,都會先存在于此池中。(6)action:后臺數(shù)據(jù)處理及數(shù)據(jù)庫訪問模塊
執(zhí)行流程如下:(1)infoChannel通過調(diào)用服務(wù)器端action獲取數(shù)據(jù)庫數(shù)據(jù)。(2)infoChannel把獲取的數(shù)據(jù)放到內(nèi)存中的modulePool中。(3)dataChannel從modulePool中取數(shù)據(jù),并傳遞到View端。(4)View端的數(shù)據(jù)通過moleManage取出。(5)moleManage把取出的數(shù)據(jù)放到內(nèi)存的crudStorePool中。(6)通過infoChannel把crudStorePool中的數(shù)據(jù)傳遞到后臺,實現(xiàn)數(shù)據(jù)的持久化操作。
ViewModel的具體應(yīng)用:(1)在前端開發(fā)中如需初始化某一模塊的數(shù)據(jù)可以調(diào)用dataChnannel中的initViewData(viewld,dataStoreParam)方法。(2)如需查詢某一節(jié)點的數(shù)據(jù)集,可以調(diào)用dataChnannel中的getDataByPath(viewId,path)。(3)如需進(jìn)行crud操作,可以調(diào)用moleManage中的相關(guān)方法。
ViewModel解決的問題:(1)向后臺的多請求操作改為通過接口統(tǒng)一調(diào)用。(2)是一個前后端通信的中間件,具有可插拔性,適用于文檔型及關(guān)系型數(shù)據(jù)庫。(3)實現(xiàn)了單例模式,避免多個實例操作同一個對象。(4)緩存大數(shù)據(jù),避免頻繁向后臺請求數(shù)據(jù)。
4Model層
Model層同其他的MVC框架一樣,Model代表特定領(lǐng)域的數(shù)據(jù)或者應(yīng)用所需的數(shù)據(jù),一個典型的特定領(lǐng)域的數(shù)據(jù)如用戶信息,或者一部電影的信息。
Model僅僅關(guān)注數(shù)據(jù)信息,不關(guān)心任何行為;不格式化數(shù)據(jù)或者影響數(shù)據(jù)在瀏覽器中的展現(xiàn);格式化數(shù)據(jù)是View層的任務(wù),同時業(yè)務(wù)邏輯層被封裝在Viewmodel中,用來和Model進(jìn)行交互。在Model層做的一個比較意外的行為是對數(shù)據(jù)的驗證,比如當(dāng)用戶輸入用戶名的時候,判斷用戶名的格式是否正確,是否有非法字符等。Model基本是按照上面的定義來實現(xiàn)的,但是會有通過ajax調(diào)用服務(wù)器服務(wù)來進(jìn)行讀寫Model數(shù)據(jù)。
MVVM框架是衍生于MVC框架的,兩者之間的最大區(qū)別在于,MVC框架中的Controller是由是由高級編程語言實現(xiàn)的,比如用Java實現(xiàn)的MVC框架,Controller是由servlet實現(xiàn),而在View中,也會用到部分的Jsp代碼;而MVVM框架中的ViewModel則是由腳本語言Javascript實現(xiàn),在View界面將不會用到Jsp代碼,從而實現(xiàn)了前端和后臺的完整分離。
優(yōu)點:(1)MVVM使并行開發(fā)更加容易,使前端開發(fā)和后端開發(fā)人員互不影響。(2)抽象化View層,減少了代碼中的業(yè)務(wù)邏輯。(3)ViewModel比事件驅(qū)動更容易測試。(4)ViewModel的測試不用關(guān)心UI的自動化和交互。
缺點:(1)對于簡單的UI,使用MVVM有點太重。(2)聲明式的數(shù)據(jù)綁定不利于調(diào)試,因為命令式的代碼可以和容易的設(shè)置斷點,這種模式就不利于設(shè)置這樣的斷點。(3)在不挑剔(non-trivial)的應(yīng)用里數(shù)據(jù)綁定可以創(chuàng)建大量的簿記(book-keeping)。(4)在大的應(yīng)用中,在獲取大量的概要(generalization)前很難設(shè)計視圖模型層。
5結(jié)語
本章主要闡述了比較流行的3個WEB框架,MVC、MVP和MVVM,并對其工作原理以及優(yōu)缺點進(jìn)行了分析和比較,并著重介紹了MVVM框架,以及如何實現(xiàn)MVVM框架的。