從MVC說起 - 概念(Version 1.0)

MVC模式可能是被人們談起最多的模式,但同時也可能是被誤解最多的模式。MVC產生的背景是什麼?MVC分別表示什麼?它與MVP之間的關係是什麼?類似的問題還有許多,在本文中,我們從MVC的起源開始探索一下它的前生今世,以試圖回答這些問題。而在隨後的文章中,我將從代碼的角度回答這些問題。

MVC模式屬於GUI模式,因此它的出現是爲了解決GUI程序設計中的一些普通存在的問題,這些問題包括:

1. 誰負責與用戶交互?

2. 誰負責處理視圖邏輯?

3. 誰負責更新模型?

4. 模型發生改變後,誰負責更新視圖?

5. M, V, C的作用範圍?

概括起來就是說M, V, C的職責是什麼?不同的模式對這些問題的回答具有很大的差異,這也正是令人混淆的原因所在。

1 經典MVC

大約在1978-1979年,Trygve Reenskaug第一次正式提出了MVC模式,它的前身是Thing-Model-View-Editor。後來此模式的一個變種作爲Xerox PARC Smalltalk-80類庫的一部分被實現,關於此實現的描述可以在Application Programming in Smalltalk-80(TM): How to use Model-View-Controller(MVC)中找到。經典MVC的結構如圖1所示,其中右側的結構圖來自Aviad's Blog中一篇文章"Twisting the MVC Triad - MVP Design Pattern",形象生動的說明了MVC模式中各個組件的功能及作用範圍。

圖1 經典MVC模式

在經典MVC中,Controller負責攔截用戶動作(即輸入),視圖負責顯示數據(即輸出),ControllerView可以直接修改Model,並且通過Model交互。View(和Controller)都觀察Model,這樣多個widget可以同步更新而不必相互通信。至於ControllerView之間的關聯更多的是爲了定位的目的。

需要注意的一個問題就是,每種模式的提出都是爲了解決當時所面臨的一些問題,就像評價歷史人物一樣我們需要站在人物所處的時代去研究他,MVC第一次提出是在70年代,它的主要目的是分離表示(Presentation)和領域模型(Domain Model),這也是它的核心所在,其後出現的各種變種也都是爲了更好的分離表示和模式。只是由於後來的GUI環境已經發生了太多的變化,例如控件的出現使得控件本身就可以攔截用戶動作,而在經典MVC中這是Controller的職責。M, V, C的作用範圍也是一個很重要的區別。在經典MVCApplication Model MVC中,用戶界面上的每一個Widget(小物件,類似於控件)都包含一個View和一個Controller,用戶對Widget的動作由它包含的Controller攔截處理,但是隨着控件的出現,控件本身已經可以攔截用戶動作,因此最終導致了Controller的消失。

注意:本段使用的是攔截(intercept)而不是處理,意思是用戶動作的處理可能會轉交給其它對象,就像我們在MVP模式中看到的那樣。

2 Application Model MVC模式

2同樣來自Avaid的博客,展示了Application Model MVC模式中各個組件的關係,職能。

 

2 Application Model MVC模式

1980年前後,從Xerox Parc實驗室分離span off出的ParcPlace ,負責Smalltalk的市場和開發,ParcPlace Smalltalk也稱爲Visual Works,在這個框架中引入了一個新的實體Application Model,它作爲ModelView之間的協調者,負責視圖邏輯(View Logic)。ViewController不在依賴Model,轉而依賴Application Model

Application Model MVC 的一個亮點在於Application Model的引入,它與MVP模式中的Presenter有點類似,都負責視圖邏輯,只是Application Model還不夠徹底,不能直接訪問View,而只能觸發某些特殊的事件,讓View監聽這些事件並更新自己,這種處理視圖的方式顯得非常笨拙。除此以外,其它方面與經典MVC基本相似。

3 Talgent MVP

1996年,Mike Potel在他的論文,MVP: Model-View-Presenter The Ta nt Programming Model for C++ and Java,正式提出了MVP模式,結構如下圖所示。

圖3 Taligent MVP模式

Model指應用程序中的數據和業務功能。Selections指出操作的是Model中的哪些數據。Commands定義了數據可以執行的操作。View作爲Model的可視化表示,它由應用程序界面中的Widgets組成。Interactors指出如何將用戶事件映射到針對Model的操作,例如鼠標移動,鍵盤輸入等。Presenter負責創建ModelSelectionsCommandsViewsInteractors,並且控制應用程序的執行。

在這個模型中,Interactor類似於經典MVCController,它負責攔截用戶動作,但是如何處理用戶動作是由Presenter決定的,它會對Model應用合適的Commands/SelectionsPresenter的功能被大大的加強了,它的角色就好像是一個子系統的管理者。

另外,在Ta nt MVP中,拋棄了每個Widget都有一個View的做法,而是多個Widgets對應一個View,而且PresenterView一般是一一對應的,或者一個Presenter管理多個Views

4 Dophin Smalltalk MVP

圖4 Dophine Smalltalk MVP

上圖摘自論文Twisting The Triad The evolution of the Dolphin Smalltalk MVP application framework,從圖中可以看出,Dophin Smalltalk MVP通過去掉了SelectionsCommandsInteractors從而簡化了Ta nt MVPDophin Smalltalk MVPTa nt MVP的主要區別體現在以下幾個方面:

1. PresenterView的關係更加緊密,Presenter可以直接修改View

2. View中的Widget已經可以攔截大部分用戶動作並處理其中的一部分。

3. 某些情況下,View可以直接更新Model,但是大多數情況下用戶事件委託給Presenter處理。

MVP設計模式分離了視圖和它的表現邏輯,允許它們獨立的改變。View可以看作是widgets的聯合體,它不包含任何描述widget如何響應用戶交互的行爲,widgets對應於Forms/Controls模型中的控件,並且viewcontroller聯繫在一起。

Widgets攔截用戶動作,然後轉交給Presenter處理,Presenter決定如何響應。當Potel討論這種交互時主要使用術語actions on model,這是通過命令系統和selections系統完成的。

MVC模式的演化可以看出,隨着技術的發展,各個組件的職責發生了很大的變化。Controller完全消失了,這是因爲隨着ViewWidget的功能越來越豐富,它承擔了攔截用戶動作和部分處理任務。View最初只是簡單的呈現模型,現在它已經囊括了Controller的職能,並且有時候可以直接操作Model(當然不提倡這樣做,因爲這涉及到可測試性的問題)。Presenter從無到有,承擔着更新模型和視圖的任務,雖然應用數據綁定技術和觀察者模式可以很好的同步ModelView,但是由於圖形用戶界面越來越豐富,交互性越來越強,這就需要更好的協調PresenterView來創造更好的用戶體驗,我們可以從PresenterView的關係越來越緊密窺見一斑。

5 Suptervising ControllerPassive View

在2006年,Martin FowlerMVP模式分爲兩個模式,分別命名爲Supervising ControllerPassive View。這種區分主要是圍繞着Presenter/Controller組件承擔表現層邏輯的深度進行的。

注意:這裏的Controller與經典MVC中的Controller概念不同,在經典MVC中,Controller主要負責處理用戶動作,而Suptervising ControllerPassive View中的Controller實際上相當於MVP模式中的Presenter。作用範圍也不一樣,在經典MVC中,用戶界面中的每一個控件都有自己的ControllerViewController只負責處理它所在的控件的用戶動作,而Suptervising ControllerPassive View中,ControllerView都是屏幕級別的。

5.1 Suptervising Controller模式

下面這幅圖描述了Suptervising Controller模式的結構

圖5 Suptervising Controller模式

Suptervising Controller負責響應來自View的用戶輸入和處理複雜的表現邏輯,View負責Model呈現和一些簡單的表現邏輯。簡單表現邏輯特指那些利用數據綁定技術或Observer模式就可以輕鬆解決的問題。

5.2 Passive View

Passive View模式的結構圖如下所示:

圖6 Passive View模式

Passive View模式與Supervising Controller模式最大的區別在於ViewModel沒有關聯,完全依賴Controller執行所有的表現層邏輯。這種結構的可測試性最強,但是需要編寫較多的表現層邏輯代碼。

至於選擇Passive View模式還是Supervising Controller模式,很大程度上取決於個人的喜好,與Passive View模式相比,Supervising Controller模式比較靈活,對於簡單的表現邏輯使用數據綁定技術,通過聲明式的編程方式,View可以隨着Model的改變而改變,

總的來說,MVC模型的演化過程就是職責重新分配的過程,決定這個過程的關鍵因素是軟件技術的發展(控件,數據綁定,模式等),和軟件工程思想的發展(可測試性,可維護性等)以及用戶體驗。

參考文獻:

1. GUI Architeture, Martin Flower

2. Twisting The Triad The evolution of the Dolphin Smalltalk MVP Application Framework, Andy Bower, Blair McGlashan

3. MVP: Model-View-Presenter The Ta nt Programming Model for C++ and Java, Mike Potel

4. Twisting the MVC Triad - MVP Design Pattern

5. Interactive Application Architecture Patterns

6. MVC WiKi

後記:

在閱讀了多篇關於MVCMVP模式論文之後,試着總結了其中的一些要點,並添加了自己的一些理解之後寫成本文。其中關於MVC或者P的職責解釋不一定全面透徹,不過基本意思應該是正確的。考慮到MVP模式在GUI編程中的重要性,建議使用一種MVC框架,使用前需要了解框架的結構。

中文有各種各樣的輸入法可以幫助我們快速輸入中文,不知道英文有沒有英文輸入法?

Powered by Zoundry

發佈了46 篇原創文章 · 獲贊 1 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章