模型-視圖-控制器MVC(Model-View-Controller)設計模式是隨著Smalltalk語言的發展而提出的,它是一個著名的用戶界面設計架構。其應用架構把應用系統劃分為3個相互協調的部分:模型(Model),包含應用程序的核心功能,封裝系統的狀態;視圖(VIEw),是模型的動態表示,並提供用戶交互界面;控制器(Controller),接受來自視圖的請求,修改模型的狀態,同時根據模型狀態的變化更新視圖。
圖1:一個基本的層次劃分MVC是分析和設計Web應用程序最常用的模式,它同時也是很多Web應用程序開發框架所依據的架構模式,它為軟件的分層及實現提供了一種穩定而成熟的結構方案和開發方法。隨著互聯網應用的不斷發展,很多傳統的應用程序被轉移到網絡平台上運行,Web應用程序也正被用來實現越來越多、越來越復雜的應用邏輯,這些都使其本身也變得越來越復雜而難以控制。
萬能JSP方法
早期的開發人員使用一種較為直接的方法來開發B/S結構的Web應用程序,這種方法明顯地帶有C/S程序開發的特點。他們不僅在視圖中實現軟件界面邏輯,還在其中實現很多應用邏輯。
以JSP程序開發為例,程序員不僅使用JSP頁面進行數據顯示和響應用戶操作,還在其中處理諸如數據庫連接、數據操作、權限控制、程序流轉等應用邏輯。
這種開發方式雖然較為直觀,但是不同類型的代碼混雜在一個頁面中,顯得零亂而不易維護。這種Web應用程序開發方法沒有形成明顯的開發框架,常被稱為Model1方法,也被戲稱為“萬能JSP方法”。
MVC模式——Web應用設計的主流
為了能有效的控制開發,MVC模式誕生了,並且成為分析和設計Web應用程序最常用的模式。
通常對於一個應用領域的問題,我們會進行如圖1所示的基本層次劃分。對於熟悉MVC模式的軟件設計師,他們通常會利用一種有效的設計模式來實現此類層次結構,即分別地設計問題域中面向應用的部件和面向數據的部件,並用一個問題語境下的控制器部件來處理它們之間的交互。
這種經典結構給問題的解決提供了一個清晰的層次模型,增加了解決方案的擴展性和維護性,而且在實現上也有很多經驗甚至代碼可以借鑒,從而也增加了軟件的成熟性,並減少了開發的難度。
因此MVC模式成為Web應用程序設計的主流方式,以此模式為基礎,出現了很多各具特色的開發框架,其中代表性的有WAF、Struts、WebWork等。這種基於MVC模式的Web應用程序開發方法被統稱為Model2方法。
遞歸MVC應運而生
雖然MVC模式對於較簡單的Web應用程序來說,是一個非常行之有效的分析模式和設計方法,但是相對於Web應用程序復雜性的快速增長來說,傳統的MVC結構已顯得過於單薄和簡單,其對應用邏輯容量和擴展性的改善也顯得相當有限。問題越來越多地表現在:
1.隨著Web應用程序中實現的應用邏輯的增加,依據MVC模式分離出來的Model層、Controller層和VIEw層都已變得更加復雜而難以控制。直接構造這些層次的風險也急劇增加。
2.Controller層中的情況更加糟糕,應用系統的數據邏輯、應用邏輯和顯示邏輯混雜在一起管理和實現,模糊了系統的層次結構,這常會使系統變得過於僵硬,由於各層次間的交互方式和過程顯得過於隨意,程序也比較難以維護。
3.數據的傳輸路線和控制過程不夠清晰,常使各個部件間產生不合理的跨層依賴,程序的整體結構受到很大影響。
4.界面的實現和流轉過於依賴控制器,大量功能單一的頁面文件造成頻繁的流轉控制和繁瑣的狀態控制,這給控制器造成很大的負擔,也會嚴重損害系統的性能和擴展性。
為了解決上述問題,一個在傳統MVC結構的基礎上遞歸地應用MVC模式的分析模式被提出。利用MVC模式解決應用程序結構問題的基本思路,去解決MVC結構本身的構造問題。
這種應用方式雖然增加了應用程序結構復雜性,卻可以使其基礎構造單元的復雜度得以快速地降低,使系統的層次結構顯得更加清晰,系統擴展性得到增強,從而為MVC應用程序以更高的效率實現更加復雜的功能打下良好的基礎。
從三角形結構到雙鍵結構
MVC在應用過程中,隨著應用程序運行環境的變化和采用的編程語言的變化,其應用形態也經歷了多次調整和改變。但是利用MVC模式進行軟件分析、設計和構造的基本思想並沒有改變。
早期的MVC結構的應用形態常呈一種三角形的結構,如圖2所示。在這種形態結構中,MVC的各個部分:Model、VIEw、Controller之間都存在著關聯或依賴關系。
圖2:MVC的三角形結構這是由於當時的應用程序普遍采用Client/Server結構(以下簡稱C/S結構)進行開發,這種結構中軟件系統的View與Model通常以相同的編程語言進行開發,同時它們之間有方便的、基於連接的數據管道進行通訊,因而VIEw中顯示和操作的數據可以直接從Model獲取,MVC形成的是一種三角形的結構形態。
在隨後的發展過程中,基於B/S結構的Web應用程序得到了大量地使用,開發人員不得不捨棄了基於連接的穩定可靠的客戶端/服務器通訊方式,代之以基於非連接的Http通訊協議。在這種應用環境中,VIEw和Model通常采用不同的語言進行開發,它們之間的數據交互變得比較不容易實現和控制。
在為了適應這種結構開發而出現的應用程序開發框架中,Controller除了實現傳統的功能外,還越來越多地被作為View和Model之間進行交互的數據通道。VIEw和Model之間的直接交互被慢慢地斷開,MVC逐漸形成了適應Web應用程序開發的雙鍵形態,如圖3所示。
圖3:適應Web應用程序的MVC雙鍵形態從雙鍵結構到MVC鏈狀結構
隨著Web應用程序的應用領域不斷擴展,應用復雜度不斷提高,雙鍵式MVC結構中的每一層都變得更加復雜和難以控制,因而將其直接作為分析和構造依據,就顯得略微有些單薄。
由於MVC結構是一種分層結構,合理的層次劃分將使其每一層完全可以獨立地進行構造,而不影響整個應用程序的結構和功能,這就使遞歸地使用MVC結構成為可能。
在這種結構中,原來的Model層、Controller層和VIEw層的內部被再次進行層次劃分,並用一個更小粒度的MVC結構去實現這種劃分。
如在View層中,可以將軟件的界面與復雜的顯示邏輯分為:View層界面和界面控制器,同時利用上層MVC結構中的控制器作為View層的Model。界面控制器為View層界面完全屏蔽了業務邏輯的具體實現方式,專注於軟件顯示邏輯的實現,而上層控制器則為整個View層屏蔽了底層的數據訪問方式,這就是一個View層的MVC結構,不妨將之稱為VIEw-MVC。如圖4所示。
圖4:VIEw-MVC的結構
正變得越來越復雜的Controller層也可以進行類似的劃分和實現,傳統的MVC結構中Controller層承擔了太多的任務,以至於它成了應用軟件在維護和擴展過程中的一個難以控制和把握的硬疙瘩。
圖5:Controler-MVC的結構
如果將其實現為如圖5所示的Controller-MVC結構,傳統的控制器將被分成界面控制器、業務控制器和數據控制器3個部分實現。應用程序的顯示邏輯完全由界面控制器來控制,對於業務控制器來說,它就是Controller。而數據控制器封裝了所有下層的數據訪問過程的具體實現方法,為業務控制器的運行提供Model層的支持。這樣就避免了系統的顯示邏輯、業務邏輯與數據邏輯的相互糾纏和牽制。
而對於Model層來說,現在絕大多數的Web應用程序中,都會使用一個O/R映射框架,將以關系形式保存在數據庫中的數據轉換成內存中的數據對象,並通過一個數據訪問對象DAO(Data Access Object)向上層應用程序提供數據持久層的訪問功能,這種機制本身就可以看做是一個Model-MVC結構,如圖6所示。
圖6:Model-MVC的結構
運行於內存中的數據對象通過一個固定的機制,將數據庫中的數據關系轉換成編程語言易於處理的對象的形式,這些就構成了這個結構自身的Model,而數據訪問對象就是這個結構的Controller,以上層Controller為代表的數據使用者相當於Model-MVC的VIEw了。
通過上述的結構劃分,復雜的Web應用程序被分成3個相對簡單的MVC結構來實現,同時各個層次內部的MVC結構中,部件之間的角色也不是固定的,而是相對的。
其中View層中的界面控制器是View-MVC中的控制器,同時也是Controller-MVC中的View,而業務控制器在Controller-MVC中是一個控制器,對於View-MVC來說就是它的Model,對於Model-MVC來說又相當於VIEw。
圖7:遞歸的MVC應用而形成的MVC鏈狀形態
在實際應用時整個應用會按這些相對的角色連接起來,形成如圖7所示的MVC鏈的形態。這就是由MVC的遞歸式應用而形成的結構。
MVC鏈狀結構的優勢
MVC鏈狀結構中,由於將傳統的MVC中的每一個層都以一個較小粒度的MVC結構來實現,從而大大提高了程序的處理能力,使Web應用程序可以支持比以往更多的應用邏輯的運行,這也使Web應用軟件能更好地適應不斷增長的需求。
在以傳統的雙鍵式MVC為分析和構造模式的應用程序中,MVC的應用粒度是達到每個業務對象的具體操作級別的。每個應用程序中可能會存在很多個平行的MVC結構,它們大致是組合/聚合關系,主要通過控制器關聯在一起,可形象地稱為MVC束。這種結構造成了龐大的文件數量,對這些文件進行管理是一筆不小的開銷。因此,在這個尺度上進行直接構造並未能充分體現MVC結構的簡單、優雅、靈活與高效。
而遞歸的MVC結構通過將各個層次分別進行構造,將每個層次的內部邏輯封裝在層次內部以一個更小的MVC結構實現,從而形成了一個MVC鏈的整體結構。
這樣就以更加豐富的層次結構復雜性換取了基本構造單元的復雜度,結構復雜性是計算機擅長處理的,基本構造單元卻主要依靠人去構造。因而遞歸地應用MVC,可以通過更豐富的層次劃分換取層次之間較低的耦合。這種分析模式已經在有些公司的業務軟件開發中被大量使用,並取得了良好的應用效果。