一包雀、學習背景
本文是繼“前端MV*框架之經典MVC”的第二篇憋他,學習動機是通過深入理解MVC孩饼、MVP、MVVM后竹挡,找到適合backbone.js框架的最佳實踐镀娶。
二、MVP歷史簡介
MVP(model-view-presenter)由經典MVC演變而來揪罕,起源于20世紀90年代的Taligent公司(IBM子公司)梯码。得益于Taligent公司的CTO(Mike Potel)在一篇論文中的推廣而普及開來。在1997年好啰,開發(fā)Dolphin Smalltalk的工程師改造了原始的MVP模式轩娶,用于重構Smalltalk的用戶界面框架。在2006年框往,微軟將MVP模式納入開發(fā)文檔鳄抒,用來開發(fā).NET framework環(huán)境下的圖形用戶界面。
三椰弊、MVP的由來
看了下Mike Potel介紹MVP的論文许溅,發(fā)現(xiàn)原始的MVP模式與如今大家公認的MVP模式相差甚遠,與經典MVC有著相同的境遇:已經被廢棄男应,不再使用闹司。如今被廣泛應用的是演變后的MVP。接下來沐飘,通過流程圖的方式來說明經典MVC是如何進化為原始MVP的:
!["經典MVC 進化為 原始MVP"](http://7bv7r7.com1.z0.glb.clouddn.com/mvp-st.png?1=1)
對于V與M的調用關系存在一種誤解:“發(fā)送狀態(tài)通知的邏輯一定寫在M里游桩,調用M進行重新渲染的邏輯一定寫在V里”牲迫。我們知道M與V是通過觀察者模式建立的關系,而建立這套關系的邏輯應該是具體的MV*框架的底層實現(xiàn)借卧,并不歸屬于M或者V盹憎。
首先回顧一下經典MVC的樣子:
一對C-V捆綁起來表示一個ui組件,C直接接受用戶輸入铐刘,并將輸入轉為相應命令來調用M的接口陪每,對M的狀態(tài)進行修改,最后通過觀察者模式對V進行重新渲染镰吵。
進化為MVP的切入點是修改C-V的捆綁關系檩禾,為了解決C-V的捆綁關系,將V進行改造疤祭,使V不僅擁有UI組件的結構盼产,還擁有接受用戶刺激的能力,這樣就能將C獨立出來勺馆。為了對用戶的刺激進行統(tǒng)一管理戏售,V只負責將用戶產生的事件傳遞給C,由C來統(tǒng)一處理草穆,這樣的好處是多個V可共用同一個C灌灾,成功將原來的兩個陣營(M、C-V)分解成三個陣營(M悲柱、V锋喜、C)。此時的C也由組件級別上升到了應用級別诗祸,然而更新V的方式仍然與經典MVC一樣:通過C更新M跑芳,通過觀察者模式更新V,為了區(qū)別于經典MVC直颅,把這種模式叫作MVP博个。最初的MVP就是這個樣子的,它仍然沒有對第一篇中MVC的短板給出解決方案功偿,但仍然是進化中必不可少的一步盆佣,這一步是由Taligent公司完成的。
四械荷、原始MVP進化為MVP(Supervising Controller)
1997年共耍,開發(fā)Dolphin Smalltalk的工程師對原始的MVP進行了改造,終于對經典MVC的短板給出了具體的解決方案吨瞎。MVP的改造過程如下圖所示:
!["原始MVP 進化為 MVP(Supervising Controller)"](http://7bv7r7.com1.z0.glb.clouddn.com/mvp-sc.png)
改造后的MVP對V的渲染采用了兩種方案:
- 對于簡單的渲染(無需對model數(shù)據(jù)進行格式轉化)痹兜,仍然通過傳統(tǒng)的觀察者模式完成。
- 對于復雜的渲染颤诀,由Presenter來完成字旭,比如設置Model數(shù)據(jù)的顏色对湃、轉化狀態(tài)字段(0、1)的含義等復雜的表現(xiàn)層邏輯遗淳。
此時Presenter負責兩個方面:接受由V傳遞過來的用戶事件拍柒、處理復雜的表現(xiàn)層邏輯;此時的Presenter也被稱為:Supervising Controller屈暗。
下面我將詳細說明MVP(Supervising Controller)示意圖中每條連線的含義:
- 線路A拆讯、線路B與原始MVP中的含義一樣:V通過觀察者模式觀察M,當M狀態(tài)改變時發(fā)送通知給V(線路A)养叛,V接到通知后調用M的接口進行重新渲染(線路B)种呐。
- 線路C與原始MVP中的含義一樣:接受由V傳遞過來的事件。
- 線路D表示通過P對V進行復雜的渲染一铅。
- 線路E表示M與P建立了觀察者模式陕贮,當M中的狀態(tài)改變并且需要執(zhí)行復雜的渲染邏輯時,M不會通知V潘飘,改為通知P,由P調用M的接口(線路F)獲取基礎數(shù)據(jù)掉缺,進行加工后渲染給V(線路D)卜录。
- 線路F表示P調用M的接口,對M中的數(shù)據(jù)執(zhí)行讀取或修改操作眶明。
五艰毒、受人追捧的MVP變種-MVP(Passive View)
對于復雜的GUI應用來說,MVP(Supervising Controller)已經能夠滿足開發(fā)者的需求搜囱,為什么還會出現(xiàn)MVP(Passive View)呢丑瞧?原因是為了滿足自動化測試的需求,編寫可測試的代碼不知何時已經成為一種時尚蜀肘,還有一系列基于測試的理念變的越來越流行:自動化回歸測試绊汹、測試驅動開發(fā)、持續(xù)集成等扮宠。對于GUI應用來說西乖,View層是很難實現(xiàn)自動化測試的,因為你不僅要測試View的結構坛增、樣式获雕,還要模擬用戶的交互行為。對于MVP模式來說收捣,Presenter是可以實現(xiàn)自動化測試的届案,所以人們開始盡可能的將應用邏輯放到Presenter中,導致原本不屬于Presenter的"簡單渲染邏輯"也被加入Presenter中罢艾,形成了一種新的MVP變種-MVP(Passive View):
!["MVP(Passive View)"](http://7bv7r7.com1.z0.glb.clouddn.com/mvp-pv.png)
為了將全部的表現(xiàn)層邏輯交給Presenter楣颠,刪除了M與V基于觀察者模式建立的映射關系尽纽,不管是簡單的渲染還是復雜的渲染,統(tǒng)統(tǒng)交給Presenter來實現(xiàn)球碉,這么做的代價是Presenter層變的非常龐大蜓斧,盡管如此,MVP(Passive View)依然成為最流行的MVP變種睁冬,以至于當我們談論MVP模式時挎春,暗指的就是MVP(Passive View)模式。
六豆拨、總結
總體來說直奋,MVP首先由經典MVC演變而來,將應用程序劃分為真正的三層結構施禾,然后進化為MVP(Supervising Controller)滿足了開發(fā)復雜GUI應用的需求脚线,最后由于自動化測試的驅動演變?yōu)镸VP(Passive View)。
參考文獻:
<a >wiki mvp</a>
<a >Martin Fowler mvp</a>
<a >Martin Fowler HumbleView</a>
<a >Mike Potel mvp</a>