作為Android最常用的架構(gòu),MVC、MVP與MVVM這三個架構(gòu)已經(jīng)是很成熟了,即使現(xiàn)在還有模塊化與插件化等方式的架構(gòu),MVP與MVVM依然是開發(fā)者常采納的方案。所以無論你是想進(jìn)階成為一名高級工程師,還是跳槽大廠進(jìn)行面試的時(shí)候,那么MVC/MVP/MVVM三個架構(gòu)的熟練掌握與使用一定是必備條件之一。
那么接下來接給大家來分享一下MVC/MVP/MVVM之間的相互聯(lián)系與優(yōu)劣勢分析,以及還有一些大廠常問的關(guān)于MVC/MVP/MVVM面試題。希望在大家架構(gòu)學(xué)習(xí)之路上給予一些幫助。另外的文末的話我也會給大家分享一套MVC/MVP/MVVM具體學(xué)習(xí)使用手冊,其中還包含MVC
MVC全名是Model--View--Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,在改進(jìn)和個性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯。其中Model層處理數(shù)據(jù),業(yè)務(wù)邏輯等;View層處理界面的顯示結(jié)果;Controller層起到橋梁的作用,來控制View層和Model層通信以此來達(dá)到分離視圖顯示和業(yè)務(wù)邏輯層。
我們往往把Android中界面部分的實(shí)現(xiàn)也理解為采用了MVC框架,常常把Activity理解為MVC模式中的Controller。
看似沒有什么特別的地方,但是由幾個需要特別View是把控制權(quán)交移給Controller,自己不執(zhí)行業(yè)務(wù)邏輯。Controller執(zhí)行業(yè)務(wù)邏輯并且操作Model,但不會直接操作View,可以說它是對View無知的。View和Model的同步消息是通過觀察者模式進(jìn)行,而同步操作是由View自己請求Model的數(shù)據(jù)然后對視圖進(jìn)行更新。MVC的優(yōu)缺點(diǎn)優(yōu)點(diǎn):
1. 把業(yè)務(wù)邏輯全部分離到Controller中,模塊化程度高。 當(dāng)業(yè)務(wù)邏輯變更的時(shí)候,不需要變更View和Model,只需要Controller 換成另外一個Controller就行了(Swappable Controller)。
2. 觀察者模式可以做到多視圖同時(shí)更新。
缺點(diǎn):Controller測試?yán)щy。因?yàn)橐晥D同步操作是由View自己執(zhí)行,而View只能在有UI的環(huán)境下運(yùn)行。在沒有UI環(huán)境下對Controller進(jìn)行單元測試的時(shí)候, Controller業(yè)務(wù)邏輯的正確性是無法驗(yàn)證的:Controller更新Model的時(shí)候,無法對View的更新操作進(jìn)行斷言。View無法組件化。View是強(qiáng)依賴特定的Model的,如果需要把這個View抽出來作為一個另外一個應(yīng)用程序可復(fù)用的組件就困難了。因?yàn)椴煌绦虻牡腄omain Model是不一樣的MVPMVP其實(shí)是MVC的一種演進(jìn)版本,它更簡單,將MVC中的Controller改為了Presenter,View通過接口與Presenter進(jìn)行交互,降低耦合,方便進(jìn)行單元測試。
View:負(fù)責(zé)繪制UI元素、與用戶進(jìn)行交互(Activity、View、Fragment都可以做為View層);Model:對數(shù)據(jù)的操作、對網(wǎng)絡(luò)等的操作,和業(yè)務(wù)相關(guān)的邏輯處理;Presenter:作為View與Model交互的中間紐帶,處理與用戶交互的邏輯。可以把Presenter理解為一個中間層的角色,它接受Model層的數(shù)據(jù),并且處理之后傳遞給View層,還需要處理View層的用戶交互等操作。關(guān)鍵點(diǎn):
View不再負(fù)責(zé)同步的邏輯,而是由Presenter負(fù)責(zé)。Presenter中既有業(yè)務(wù)邏輯也有同步邏輯。View需要提供操作界面的接口給Presenter進(jìn)行調(diào)用。(關(guān)鍵)對比在MVC中,Controller是不能操作View的,View也沒有提供相應(yīng)的接口;而在MVP當(dāng)中,Presenter可以操作View,View需要提供一組對界面操作的接口給Presenter進(jìn)行調(diào)用;Model仍然通過事件廣播自己的變更,但由Presenter監(jiān)聽而不是View。
MVP(Passive View)的優(yōu)缺點(diǎn)優(yōu)點(diǎn):1. 便于測試。 Presenter對View是通過接口進(jìn)行,在對Presenter進(jìn)行不依賴UI環(huán)境的單元測試的時(shí)候??梢酝ㄟ^Mock一個View對象,這個對象只需要實(shí)現(xiàn)了View的接口即可。然后依賴注入到Presenter中,單元測試的時(shí)候就可以完整的測試Presenter業(yè)務(wù)邏輯的正確性。
2. View可以進(jìn)行組件化。 在MVP當(dāng)中,View不依賴Model。這樣就可以讓View從特定的業(yè)務(wù)場景中脫離出來,可以說View可以做到對業(yè)務(wù)邏輯完全無知。它只需要提供一系列接口提供給上層操作。這樣就可以做高度可復(fù)用的View組件。
缺點(diǎn):Presenter中除了業(yè)務(wù)邏輯以外,還有大量的View->Model,Model->View的手動同步邏輯,造成Presenter比較笨重,維護(hù)起來會比較困難。MVVMMVVM模式(Model--View--ViewModel模式),和MVP模式相比,MVVM 模式用ViewModel替換了Presenter ,其他層基本上與 MVP 模式一致,ViewModel可以理解成是View的數(shù)據(jù)模型和Presenter的合體。
MVVM采用雙向綁定(data-binding):View的變動,自動反映在ViewModel,反之亦然,這種模式實(shí)際上是框架替應(yīng)用開發(fā)者做了一些工作(相當(dāng)于ViewModel類是由庫幫我們生成的),開發(fā)者只需要較少的代碼就能實(shí)現(xiàn)比較復(fù)雜的交互。
MVVM的調(diào)用關(guān)系MVVM的調(diào)用關(guān)系和MVP一樣。但是,在ViewModel當(dāng)中會有一個叫Binder,或者是Data-binding engine的東西。以前全部由Presenter負(fù)責(zé)的View和Model之間數(shù)據(jù)同步操作交由給Binder處理。你只需要在View的模版語法當(dāng)中,指令式地聲明View上的顯示的內(nèi)容是和Model的哪一塊數(shù)據(jù)綁定的。當(dāng)ViewModel對進(jìn)行Model更新的時(shí)候,Binder會自動把數(shù)據(jù)更新到View上去,當(dāng)用戶對View進(jìn)行操作(例如表單輸入),Binder也會自動把數(shù)據(jù)更新到Model上去。這種方式稱為:Two-way data-binding,雙向數(shù)據(jù)綁定??梢院唵味磺‘?dāng)?shù)乩斫鉃橐粋€模版引擎,但是會根據(jù)數(shù)據(jù)變更實(shí)時(shí)渲染。
關(guān)鍵點(diǎn):
MVVM把View和Model的同步邏輯自動化了。以前Presenter負(fù)責(zé)的View和Model同步不再手動地進(jìn)行操作,而是交由框架所提供的Binder進(jìn)行負(fù)責(zé)。
只需要告訴Binder,View顯示的數(shù)據(jù)對應(yīng)的是Model哪一部分即可。
MVVM的優(yōu)缺點(diǎn)優(yōu)點(diǎn):1. 提高可維護(hù)性。 解決了MVP大量的手動View和Model同步的問題,提供雙向綁定機(jī)制。提高了代碼的可維護(hù)性。
2. 簡化測試。 因?yàn)橥竭壿嬍墙挥葿inder做的,View跟著Model同時(shí)變更,所以只需要保證Model的正確性,View就正確。大大減少了對View同步更新的測試。
缺點(diǎn):過于簡單的圖形界面不適用,或說牛刀殺雞。對于大型的圖形應(yīng)用程序,視圖狀態(tài)較多,ViewModel的構(gòu)建和維護(hù)的成本都會比較高。數(shù)據(jù)綁定的聲明是指令式地寫在View的模版當(dāng)中的,這些內(nèi)容是沒辦法去打斷點(diǎn)debug的。常見面試筆試真題Android中的MVC是什么?有什么特點(diǎn)?參考回答:
M:Model,數(shù)據(jù)模塊,提供數(shù)據(jù);
V:View,UI模塊,視圖層;
C:Controller,控制模塊,相當(dāng)于Activity。
Controller操作Model層的數(shù)據(jù),并且將數(shù)據(jù)返回給View層展示。Activity既要處理Controller的邏輯也要處理View的邏輯,導(dǎo)致Activity的代碼過于臃腫。View層和Model層之間耦合性大,導(dǎo)致不易于維護(hù)和擴(kuò)展。
用過MVP構(gòu)建過項(xiàng)目嗎?談?wù)勀銓λ恼J(rèn)識。參考回答:
MVP就是在MVC上增加了一個接口,因此也降低一層耦合度,這樣View就不會直接訪問Model。
Presenter完全將Model和View解耦,主要邏輯都集中在Presenter中。和View沒有直接關(guān)聯(lián),因?yàn)樗芡ㄟ^View中定義好的接口進(jìn)行交互。這樣當(dāng)View需要修改的時(shí)候,就不用去Presenter里改動。View層就只需處理跟UI有關(guān)的邏輯即可。
MVP低耦合、重用方便,而且測試也方便,但使用了接口去設(shè)計(jì)邏輯復(fù)雜的頁面時(shí)也會導(dǎo)致代碼中接口過多或龐大。
簡單說一下你是如何使用MVP去構(gòu)建一個項(xiàng)目的。參考回答:
我們可以按照MVP的各個模塊去設(shè)計(jì)代碼。
1)首先定義Model,創(chuàng)建好Model接口和回調(diào)接口,接著就是創(chuàng)建一個實(shí)現(xiàn)類,重寫Model接口里的方法;2)接著就是設(shè)計(jì)View模塊,負(fù)責(zé)UI展示與操作;?3)用Activity去實(shí)現(xiàn)這個View接口;?4)創(chuàng)建Presenter,互相持有對象,讓View和Model能交互;?5)最后用Activity創(chuàng)建Presenter對象并且調(diào)用它的方法來處理業(yè)務(wù)邏輯
以上便是整個MVP構(gòu)建項(xiàng)目的思路,并不是一定要該思路,要結(jié)合實(shí)際情況去考慮。
Model-View-ViewModel,對比MVP,就是將Presenter替換為ViewModel。ViewModel和Model/View進(jìn)行了雙向綁定。當(dāng)View發(fā)生改變時(shí),ViewModel會通知Model進(jìn)行更新數(shù)據(jù)。而Model數(shù)據(jù)更新后,ViewModel會通知View更新顯示。因?yàn)镈ata Binding能將數(shù)據(jù)綁定到xml中, 而且還有ViewModel和LiveData等,使得MVVM用起來更加方便。
要說MVVM就真的完美嗎?也不是,因?yàn)樗沟脭?shù)據(jù)與視圖雙向綁定了,所以當(dāng)出現(xiàn)問題的時(shí)候不好找到出錯源頭,是數(shù)據(jù)問題還是視圖屬性修改導(dǎo)致的,可能需要時(shí)間去尋找。所以使用的時(shí)候要注意。
模塊化是什么?它與組件化又有什么區(qū)別?參考回答:
通常一個項(xiàng)目會采用下面的架構(gòu),如圖所示:
產(chǎn)品層:即應(yīng)用層,如果有三個項(xiàng)目,則該層有三個塊;
通用業(yè)務(wù)層:放置公司多個項(xiàng)目的通用業(yè)務(wù)模塊,這些模塊是跟業(yè)務(wù)有關(guān),比如文件等資源下載和上傳;
基礎(chǔ)層:基礎(chǔ)庫,比如網(wǎng)絡(luò)請求,圖片壓縮等邏輯模塊、通用UI模塊和第三方庫。
而通常新建一個app項(xiàng)目時(shí)是按照類型劃分的(activity、fragment、view、和utils等等),或者按照業(yè)務(wù)劃分,每個業(yè)務(wù)模塊就是一個包,每個包再按照不同類型細(xì)分下去。
模塊化是一種軟件設(shè)計(jì)技術(shù),它能將項(xiàng)目的功能拆分為獨(dú)立、可交換的模塊。每個模塊都包含執(zhí)行單獨(dú)功能的必要內(nèi)容。而組件化也是設(shè)計(jì)技術(shù),它強(qiáng)調(diào)將一個軟件系統(tǒng)拆分為獨(dú)立的組件,而這些組件可以是模塊也可以是web資源等。
兩者目的都是重用和解耦,主要區(qū)別在于模塊化側(cè)重于重用,組件化更側(cè)重于業(yè)務(wù)解耦。
如果要構(gòu)建一個項(xiàng)目,該選擇MVC還是MVP,亦或是MVVM?參考回答:
如果要構(gòu)建的項(xiàng)目簡單不是很復(fù)雜的時(shí)候,其實(shí)不需要使用構(gòu)建模式來構(gòu)建項(xiàng)目的,因?yàn)檫@樣的項(xiàng)目不需要太大改動,只需封裝好每個模塊,然后要使用的時(shí)候直接調(diào)用即可。
如果要構(gòu)建的項(xiàng)目主要是展示UI和數(shù)據(jù),為了更友好地與用戶交互,比較適合使用MVVM來構(gòu)建,因?yàn)樵擃愴?xiàng)目的大多數(shù)業(yè)務(wù)邏輯都集中在后端,而勢必要經(jīng)常對視圖進(jìn)行改動,所以使用MVVM能非常好地進(jìn)行視圖屬性修改。
如果要構(gòu)建的項(xiàng)目要處理較多業(yè)務(wù)邏輯或者是屬于工具類app的,那就使用MVP比較合適,使用MVVM也是可以的。
當(dāng)然,MVC也不是說就用不上,平時(shí)也可以使用MVC來構(gòu)建一些學(xué)習(xí)項(xiàng)目來一層一層地進(jìn)行封裝。
總結(jié)以上,可以看到。從MVC->MVP->MVVM,就像一個打怪升級的過程。后者解決了前者遺留的問題,把前者的缺點(diǎn)優(yōu)化成了優(yōu)點(diǎn)。同樣的Demo功能,代碼從最開始的一堆文件,優(yōu)化成了最后只需要20幾行代碼就完成。當(dāng)然,以上也只是對MVX三種架構(gòu)模式之間的區(qū)分和優(yōu)缺點(diǎn)做了簡單闡述,好讓大家對MVX三種架構(gòu)模式能有一個清晰的認(rèn)識,同時(shí)也希望可以給對這些模式理解比較模糊的同學(xué)帶來一些參考和思路。
另外如果想要對MVX三種架構(gòu)模式進(jìn)行進(jìn)階深入學(xué)習(xí)的同學(xué),我這邊整理了一份《Android架構(gòu)開發(fā)手冊》,也就是我在開頭說的包含MVX進(jìn)階學(xué)習(xí)+大廠架構(gòu)實(shí)戰(zhàn)演化+Jetapck全套組件學(xué)習(xí)的218頁的PDF學(xué)習(xí)筆記。整理不易,有需要的同學(xué),可以點(diǎn)贊本文支持下,然后私信來找我獲?。?/strong>