再談MV*(MVVM MVP MVC)模式的設計原理—封裝與解耦

精煉并增補于:界面之下:還原真實的MV*模式

圖形界面的應用程序提供給用戶可視化的操作界面,這個界面提供給數據和信息。用戶輸入行為(鍵盤砍鸠,鼠標等)會執(zhí)行一些應用邏輯湃望,應用邏輯(application logic)可能會觸發(fā)一定的業(yè)務邏輯(business logic)對應用程序數據的變更,數據的變更自然需要用戶界面的同步變更以提供最準確的信息院喜。

在開發(fā)應用程序的時候亡蓉,以求更好的管理應用程序的復雜性,基于職責分離(Speration of Duties)的思想都會對應用程序進行分層喷舀。在開發(fā)圖形界面應用程序的時候砍濒,會把管理用戶界面的層次稱為View應用程序的數據為Model(注意這里的Model指的是Domain Model硫麻,這個應用程序對需要解決的問題的數據抽象爸邢,不包含應用的狀態(tài),可以簡單理解為對象)拿愧。Model提供數據操作的接口杠河,執(zhí)行相應的業(yè)務邏輯。

有了View和Model的分層浇辜,那么問題就來了:View如何同步Model的變更券敌,View和Model之間如何粘合在一起?

MV*模式解決什么問題

MV*就是實現了領域模型數據和UI層的解耦

MVC柳洋、MVP待诅、MVVM對其解耦的思路的不同。從歷史的角度來看熊镣,MVC卑雁、MVP和MVVM是一種進化的關系。但是鑒于項目的規(guī)模以及模式實現的方式不同绪囱,不同的MV*模式各有其優(yōu)點和缺點测蹲,難分孰好孰壞

但是業(yè)界越來越認為:MVVM是前端領域最好的MV*模式毕箍。Angular弛房、Vue是MVVM模式典范

MVC的依賴關系

MVC出了把應用程序分成View、Model層而柑,還額外的加了一個Controller層文捶,職責為進行Model和View之間的協(xié)作(路由荷逞、輸入預處理等)的應用邏輯(application logic)。

Model主要是與業(yè)務數據有關粹排。

View是應用程序數據的可視化表示种远。

Controller管理應用程序中Model和View之間的邏輯和協(xié)調。

用戶對View的輸入等操作并不會在View的相關模塊中處理邏輯顽耳,而是由Controller層獲得這些操作(所謂的Pass Call)坠敷,并由Controller層對這些操作中的數據經過應用邏輯的操作,然后在調用Model層的接口射富,將數據交給Model層膝迎。Model層執(zhí)行與業(yè)務邏輯相關的操作,并更新數據胰耗。Model和View通過觀察者模式聯系在一起限次,即View是Model的觀察者,當Model數據變動之后柴灯,通知View層進行數據更新卖漫。

MVC優(yōu)點

把業(yè)務邏輯全部分離到Controller中,模塊化程度高赠群。當業(yè)務邏輯變更的時候羊始,不需要變更View和Model,只需要Controller換成另外一個Controller就行了(Swappable Controller)查描。

觀察者模式可以做到多視圖同時更新突委。

MVC缺點

Controller測試困難。因為視圖同步操作是由View自己執(zhí)行叹誉,而View只能在有UI的環(huán)境下運行鸯两。在沒有UI環(huán)境下對Controller進行單元測試的時候,Controller業(yè)務邏輯的正確性是無法驗證的:Controller更新Model的時候长豁,無法對View的更新操作進行斷言。

View無法組件化忙灼。View是強依賴特定的Model的匠襟,如果需要把這個View抽出來作為一個另外一個應用程序可復用的組件就困難了。因為不同程序的的Domain Model是不一樣的

MVP模式

MVP比起MVC模式该园,它的特點很明顯酸舍。MVP中M和V之間的依賴關系被消除了。

在MVC中里初,M和V之間通過觀察者模式依賴啃勉。這種依賴關系在MVP中被轉移到M和P層中。這樣一來P層必須通過一定的機制通知V層進行數據的更新双妨。所以MVP模式中V層中提供了供P層調用的接口淮阐。P層作為觀察者獲得數據變化是叮阅,將調用V層的接口將變化反映到V層中。

在MVP中:

Model層依然是主要與業(yè)務數據有關泣特。浩姥、

View依然是應用程序的可視化表示,但是在MVP中它對領域數據(Model層)完全無知状您,View不再負責同步的邏輯勒叠,而是由Presenter負責。Presenter中既有應用程序邏輯也有同步邏輯膏孟。所以比起MVC中View層更輕了眯分。但是,View需要提供操作界面的接口給Presenter進行調用

Presenter層比較重柒桑,它不僅調用Model的接口颗搂,也調用View的接口。而且需要作為觀察者獲得Model的數據更新幕垦。

MVP(Passive View)的調用關系

MVP(Passive View)優(yōu)點

便于測試丢氢。Presenter對View是通過接口進行,在對Presenter進行不依賴UI環(huán)境的單元測試的時候先改【尾欤可以通過Mock一個View對象,這個對象只需要實現了View的接口即可仇奶。然后依賴注入到Presenter中貌嫡,單元測試的時候就可以完整的測試Presenter應用邏輯的正確性。這里根據上面的例子給出了Presenter的單元測試樣例该溯。

View可以進行組件化岛抄。在MVP當中,View不依賴Model狈茉。這樣就可以讓View從特定的業(yè)務場景中脫離出來夫椭,可以說View可以做到對業(yè)務完全無知。它只需要提供一系列接口提供給上層操作氯庆。這樣就可以做到高度可復用的View組件蹭秋。

MVP(Passive View)缺點

Presenter中除了應用邏輯以外,還有大量的View->Model堤撵,Model->View的手動同步邏輯仁讨,造成Presenter比較笨重,維護起來會比較困難实昨。

MVP(Supervising Controller)

Supervising Controller模式中洞豁,Presenter會把一部分簡單的同步邏輯交給View自己去做,Presenter只負責比較復雜的、高層次的UI操作丈挟,所以可以把它看成一個Supervising Controller刁卜。

因為Supervising Controller用得比較少,MVVM可以看作是一種特殊的MVP(Passive View)模式,或者說是對MVP模式的一種改良礁哄。

MVVM的依賴

Model-View-ViewModel模式中长酗,M層數據的變化不是通過觀察者模式通知到V層的(即沒有M和V的依賴),也不是通過VM層調用V層的接口將數據傳遞給V層的(這意味著用戶代碼不需要手動更新V層)桐绒。而是通過在VM層實現一個特殊的binder夺脾,將數據從M層直接綁定到V層。這樣ViewModel層了解Model層茉继,View層了解ViewModel層咧叭。

ViewModel充當了一個數據轉換器的作用。它將Model信息轉換為View信息烁竭,還將命令從View傳遞到Model菲茬。在這里,View可以訪問ViewModel,ViewModel可以訪問Model派撕。

MVVM的調用關系和MVP一樣婉弹。但是,在ViewModel當中會有一個叫Binder终吼,或者是Data-binding engine的東西镀赌。以前全部由Presenter負責的View和Model之間數據同步操作交由給Binder處理。你只需要在View的模版語法當中际跪,指令式地聲明View上的顯示的內容是和Model的哪一塊數據綁定的商佛。當ViewModel對進行Model更新的時候,Binder會自動把數據更新到View上去姆打,當用戶對View進行操作(例如表單輸入)良姆,Binder也會自動把數據更新到Model上去。這種方式稱為:Two-way data-binding幔戏,雙向數據綁定玛追。可以簡單而不恰當地理解為一個模版引擎评抚,但是會根據數據變更實時渲染豹缀。

MVVM把View和Model的同步邏輯自動化了。以前Presenter負責的View和Model同步不再手動地進行操作慨代,而是交由框架所提供的Binder進行負責。只需要告訴Binder啸如,View顯示的數據對應的是Model哪一部分即可侍匙。

MVVM優(yōu)點

雙向綁定技術,當Model變化時,View-Model會自動更新想暗,View也會自動變化妇汗。很好做到數據的一致性,不用擔心说莫,在模塊的這一塊數據是這個值杨箭,在另一塊就是另一個值了。所以 MVVM模式有些時候又被稱作:model-view-binder模式储狭。

提高可維護性互婿。解決了MVP大量的手動View和Model同步的問題,提供雙向綁定機制辽狈。提高了代碼的可維護性慈参。

簡化測試。因為同步邏輯是交由Binder做的刮萌,View跟著Model同時變更驮配,所以只需要保證Model的正確性,View就正確着茸。大大減少了對View同步更新的測試壮锻。

MVVM缺點

過于簡單的圖形界面不適用,或說牛刀殺雞涮阔。

對于大型的圖形應用程序猜绣,視圖狀態(tài)較多,ViewModel的構建和維護的成本都會比較高澎语。

數據綁定的聲明是指令式地寫在View的模版當中的途事,這些內容是沒辦法去打斷點debug的。

一個大的模塊中model也會很大擅羞,雖然使用方便了也很容易保證了數據的一致性尸变,當時長期持有,不釋放內存就造成了花費更多的內存减俏。

數據雙向綁定不利于代碼重用召烂。客戶端開發(fā)最常用的重用是View娃承,但是數據雙向綁定技術奏夫,讓你在一個View都綁定了一個model,不同模塊的model都不同历筝。那就不能簡單重用View了酗昼。

如有更新,只在原文進行:再談MV*(MVVM MVP MVC)模式的設計原理-封裝與解耦梳猪,如果不妥之處麻削,親留言告知。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呛哟,隨后出現的幾起案子叠荠,更是在濱河造成了極大的恐慌,老刑警劉巖扫责,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榛鼎,死亡現場離奇詭異,居然都是意外死亡鳖孤,警方通過查閱死者的電腦和手機者娱,發(fā)現死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淌铐,“玉大人肺然,你說我怎么就攤上這事⊥茸迹” “怎么了际起?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吐葱。 經常有香客問我街望,道長,這世上最難降的妖魔是什么弟跑? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任灾前,我火速辦了婚禮,結果婚禮上孟辑,老公的妹妹穿的比我還像新娘哎甲。我一直安慰自己,他們只是感情好饲嗽,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布炭玫。 她就那樣靜靜地躺著,像睡著了一般貌虾。 火紅的嫁衣襯著肌膚如雪吞加。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天尽狠,我揣著相機與錄音衔憨,去河邊找鬼。 笑死袄膏,一個胖子當著我的面吹牛践图,可吹牛的內容都是我干的。 我是一名探鬼主播沉馆,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼平项,長吁一口氣:“原來是場噩夢啊……” “哼赫舒!你這毒婦竟也來了悍及?” 一聲冷哼從身側響起闽瓢,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎心赶,沒想到半個月后扣讼,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡缨叫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年椭符,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耻姥。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡销钝,死狀恐怖,靈堂內的尸體忽然破棺而出琐簇,到底是詐尸還是另有隱情蒸健,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布婉商,位于F島的核電站似忧,受9級特大地震影響,放射性物質發(fā)生泄漏丈秩。R本人自食惡果不足惜盯捌,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蘑秽。 院中可真熱鬧饺著,春花似錦、人聲如沸肠牲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽埂材。三九已至塑顺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間俏险,已是汗流浹背严拒。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留竖独,地道東北人裤唠。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像莹痢,于是被迫代替她去往敵國和親种蘸。 傳聞我的和親對象是個殘疾皇子墓赴,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內容