如何將我們的安卓應(yīng)用程序組織成相應(yīng)的邏輯部件這個(gè)問題已經(jīng)被討論了很長時(shí)間了屡立。目前大部分開發(fā)人員都拋棄了傳統(tǒng)的Model View Controller(MVC)架構(gòu)褂痰,而更青睞于更加模塊化亩进,更易于測試的新的架構(gòu)。
目前Model View Presenter (MVP) 以及Model View ViewModel (MVVM)這兩種新的架構(gòu)成為了被廣泛接受的替代方法缩歪。關(guān)于這兩個(gè)架構(gòu)孰優(yōu)孰劣的辯論從未停止過归薛,然而試圖證明一種架構(gòu)遠(yuǎn)優(yōu)于另一種架構(gòu)的觀點(diǎn)大多都是基于主觀的判斷。這篇文章希望盡可能地撇開主觀情感匪蝙,來理性地分析這三種架構(gòu)的價(jià)值和潛力苟翻,然后為您在開發(fā)時(shí)選擇合適的架構(gòu)時(shí)提供建議。
MVC
Model View Controller 架構(gòu)在宏觀上將應(yīng)用的分為三種邏輯部件骗污,每一種包含相應(yīng)的職責(zé)崇猫。
Model
Model對于一個(gè)應(yīng)用來說,通常包含了數(shù)據(jù)需忿,狀態(tài)和邏輯诅炉,是我們的應(yīng)用中的核心部件。它不會(huì)與View和Controller綁定屋厘,正因?yàn)檫@樣涕烧,通常模型的組件可以在不同的上下文中被復(fù)用。
View
View是對Model的展示汗洒,該部件的職責(zé)是渲染用戶圖形界面并在用戶與界面產(chǎn)生互動(dòng)時(shí)與Controller進(jìn)行交互议纯。通常,在MVC架構(gòu)中View部件不了解底層的Model部件溢谤,不清楚當(dāng)前的裝態(tài)是什么也不知道當(dāng)用戶進(jìn)行操作時(shí)邏輯上究竟會(huì)發(fā)生什么變化瞻凤。但這正是MVC架構(gòu)的優(yōu)勢憨攒,View與業(yè)務(wù)邏輯的耦合越低就越靈活。
Controller
Controller是整個(gè)應(yīng)用的粘合劑阀参,當(dāng)View通知Controller用戶做出了一些操作時(shí)肝集,由Controller負(fù)責(zé)決定如何與相應(yīng)的Model交互。同時(shí)蛛壳,當(dāng)Model的數(shù)據(jù)發(fā)生改變時(shí)杏瞻,Controller負(fù)責(zé)根據(jù)這些數(shù)據(jù)的變化來決定更新相應(yīng)的View的狀態(tài)。在安卓應(yīng)用中Controller通常Activity和Fragment實(shí)現(xiàn)衙荐。
評價(jià)
MVC架構(gòu)很好地分離了model和view捞挥,但是controller存在以下問題:
可測試性:controller與安卓API綁定而難以進(jìn)行單元測試
模塊化和靈活性:controller與view的高度耦合導(dǎo)致view修改時(shí)我們往往需要修改controller
可維護(hù)性:隨著應(yīng)用規(guī)模變大,越來越多的代碼開始轉(zhuǎn)移到控制器中忧吟,使得它們變得笨重和脆弱砌函。
如何解決這些問題呢?MVP提供了方案瀑罗。
MVP
Model
與MVC一樣
View
View唯一的變化在于胸嘴,現(xiàn)在的Activity/Fragment被視為view的一部分。我們不再試圖對抗他們緊密耦合的自然趨勢斩祭。一種好的做法是讓Activity實(shí)現(xiàn)view接口劣像,這樣Presenter就會(huì)可以針對接口編程。這消除了將其耦合到任何特定view摧玫,并允許對view的mock實(shí)現(xiàn)進(jìn)行簡單的單元測試耳奕。
Presenter
Presenter實(shí)際上是來自MVC的控制器,只不過它不再與View耦合诬像,只是一個(gè)接口屋群。這解決了MVC的可測試性問題以及模塊化/靈活性問題。實(shí)際上坏挠,MVP純粹主義者會(huì)爭辯說芍躏,Presenter絕不應(yīng)該包含任何對Android API或代碼的引用。
評價(jià)
這種架構(gòu)更加簡潔降狠。只要視圖實(shí)現(xiàn)了相應(yīng)的接口对竣,我們可以輕松地對Presenter邏輯進(jìn)行單元測試,因?yàn)樗皇苋魏蜛ndroid特定視圖和API的限制榜配,也允許我們使用任何其他的視圖否纬。
問題
可維護(hù)性:Presenter,就像Controller一樣蛋褥,隨著時(shí)間的推移临燃,它們傾向于增加額外的業(yè)務(wù)邏輯。在某些時(shí)候,開發(fā)人員經(jīng)常會(huì)遇到難以分解的大型笨重的Presenter膜廊。
MVVM
Android的數(shù)據(jù)綁定使得MVVM架構(gòu)具有更易于測試和模塊化的優(yōu)點(diǎn)乏沸,同時(shí)還減少了我們必須編寫的連接視圖+模型的代碼。
Model
與MVC一樣
View
View以靈活的方式綁定到由viewModel暴露的可觀察的變量和操作溃论。
ViewModel
ViewModel負(fù)責(zé)包裝模型并準(zhǔn)備視圖所需的可觀察數(shù)據(jù)屎蜓。它還為視圖提供了將事件傳遞給模型的鉤子痘昌。然而钥勋,ViewModel并不與視圖綁定。
評估
單元測試變得更加容易辆苔,當(dāng)測試時(shí)算灸,只需要驗(yàn)證在模型更改時(shí)可觀察的變量是否被正確地設(shè)置。沒有必要像采用MVP架構(gòu)時(shí)那樣mock測試的視圖驻啤。
問題
可維護(hù)性:由于視圖可以綁定到變量和表達(dá)式菲驴,無關(guān)的展示邏輯會(huì)隨著時(shí)間的推移而蔓延,將大量添加XML中的代碼骑冗。為了避免這種情況赊瞬,應(yīng)當(dāng)直接從ViewModel獲取值,而不要從視圖綁定表達(dá)式中計(jì)算或推演它們贼涩。
總結(jié)
MVP和MVVM都比MVC更好地將應(yīng)用程序分解為模塊化的單用途組件巧涧,但它們也增加了您的應(yīng)用的復(fù)雜性。具有數(shù)據(jù)綁定的MVVM具有很強(qiáng)的吸引力遥倦,因?yàn)樗裱呦鄳?yīng)性的編程模型并產(chǎn)生較少的代碼谤绳。