首先辨析一下架構(gòu)模式和設(shè)計(jì)模式的關(guān)系:
MVP、MVC、MVVM是三種常見的前端架構(gòu)模式,通過分離關(guān)注點(diǎn)來改進(jìn)代碼組織方式。而設(shè)計(jì)模式只是為了解決一類問題而總結(jié)出的抽象方法。一種架構(gòu)模式往往能使用多種設(shè)計(jì)模式,如工廠模式、抽象模式、單例模式。本文整合了網(wǎng)上一些博客的觀點(diǎn),僅作學(xué)習(xí)記錄,參考博文已附鏈接。
MVC和MVP
https://cloud.tencent.com/developer/article/1383090
https://blog.csdn.net/qq_31852701/article/details/52946127
MVVM和ViewModel
在介紹這三種架構(gòu)及個(gè)人理解之前聲明一點(diǎn),任何架構(gòu)都沒有絕對(duì)的劃分,這只是一種思想和良好的代碼習(xí)慣,我的理解也不深入,歡迎大家批評(píng)指正~
MVC
Model模型層,和數(shù)據(jù)獲取、處理相關(guān)的層,負(fù)責(zé)存儲(chǔ)系統(tǒng)的中心數(shù)據(jù)。M最接近獲取數(shù)據(jù)的API或數(shù)據(jù)庫。對(duì)數(shù)據(jù)庫的操作、以及其他和數(shù)據(jù)有關(guān)的的操作都應(yīng)該在Model里面處理,當(dāng)然對(duì)業(yè)務(wù)計(jì)算等操作也是必須放在的該層的。
View視圖UI層,負(fù)責(zé)將信息顯示給用戶,可以定義多個(gè)View,通過Controller的調(diào)用,對(duì)Model進(jìn)行不同的展示。
Controller控制層,負(fù)責(zé)處理用戶和應(yīng)用的交互,從視圖讀取數(shù)據(jù),通過監(jiān)聽事件響應(yīng)用戶對(duì)View的操作,再調(diào)用Model對(duì)數(shù)據(jù)進(jìn)行更新,完成model與view的同步。
MVC重要特點(diǎn)就是兩種分離:
視圖和數(shù)據(jù)模型的分離:使用不同的視圖對(duì)相同的數(shù)據(jù)進(jìn)行展示;分離可視和不可視的組件,能夠?qū)δP瓦M(jìn)行獨(dú)立測(cè)試。因?yàn)榉蛛x了可視組件減少了外部依賴?yán)跍y(cè)試。(數(shù)據(jù)庫也是一種外部組件)
視圖和表現(xiàn)邏輯(Controller)的分離:Controller是一個(gè)表現(xiàn)邏輯的組件,并非一個(gè)業(yè)務(wù)邏輯組件。MVC可以作為表現(xiàn)模式也可以作為建構(gòu)模式,意味這Controller也可以是業(yè)務(wù)邏輯。分離邏輯和具體展示,能夠?qū)壿嬤M(jìn)行獨(dú)立測(cè)試。
大家可以這樣來理解:模型是我們想要操作的對(duì)象,但它沒有用戶界面。視圖表示它在屏幕上的顯示,代表流向用戶的數(shù)據(jù)。控制器定義用戶界面對(duì)用戶請(qǐng)求的響應(yīng)方式,負(fù)責(zé)把用戶的動(dòng)作轉(zhuǎn)成針對(duì)Model的操作。Model 通過更新View的數(shù)據(jù)來反映數(shù)據(jù)的變化。
我看過網(wǎng)上很多博主畫的流程圖有失偏頗,甚至把MVC和MVP相混淆,所以我放一張書上的圖,相對(duì)更權(quán)威吧。

我大致講一下我對(duì)這張圖的理解,當(dāng)然,我的理解也不完全正確,歡迎大家向我提出質(zhì)疑。
View—>Model 視圖是解釋模型的載體,可以直接查詢已適配的模型得到數(shù)據(jù)(可能適配用詞不當(dāng))
View—>Controllerl—>View 視圖將用戶輸入發(fā)給控制器,控制器根據(jù)用戶請(qǐng)求選擇響應(yīng)的視圖,并將對(duì)應(yīng)的模型傳給該視圖。
View—>Controllerl—>Model—>View用戶有模型更新的請(qǐng)求,導(dǎo)致模型狀態(tài)發(fā)生改變,而模型將狀態(tài)的改變反饋給所適配的視圖。
這么來看,Model、View、Controller三者之間是相互可見的,而Controller到底是表現(xiàn)邏輯的組件還是業(yè)務(wù)邏輯的組件,并不清晰。模塊之間界限不明顯,Model和View中也存在少量邏輯代碼,耦合度低。再者,雖然Model和View之間有關(guān)聯(lián),但數(shù)據(jù)的改變和更新卻必須經(jīng)過Controller,由開發(fā)者手動(dòng)實(shí)現(xiàn),若數(shù)據(jù)更新的地方比較多,維護(hù)數(shù)據(jù)狀態(tài)的代碼也會(huì)復(fù)雜起來。帶著這兩個(gè)不足之處,我們來看看MVP和MVVM解決了什么問題吧。
MVVM
MVVM 是Model-View-ViewModel 的縮寫,MVVM與MVC最大的區(qū)別就是:它實(shí)現(xiàn)了View和Model的自動(dòng)同步,也就是當(dāng)Model的屬性改變時(shí),該屬性對(duì)應(yīng)View層顯示會(huì)自動(dòng)改變。在MVVM架構(gòu)下,View 和 Model 之間并沒有直接的聯(lián)系,而是通過ViewModel進(jìn)行交互,Model 和 ViewModel 之間的交互是雙向的, 因此View 數(shù)據(jù)的變化會(huì)同步到Model中,而Model 數(shù)據(jù)的變化也會(huì)立即反應(yīng)到View 上。開發(fā)者只需關(guān)注業(yè)務(wù)邏輯,不需要關(guān)注數(shù)據(jù)狀態(tài)的同步問題,復(fù)雜的數(shù)據(jù)狀態(tài)維護(hù)完全由 MVVM 來統(tǒng)一管理。
比如說,我們可以通過一個(gè)String類型的狀態(tài)來表示一個(gè)TextView,同理,我們也可以通過一個(gè)List<T>類型的狀態(tài)來維護(hù)一個(gè)RecyclerView的列表——在實(shí)際開發(fā)中我們通過觀察這些數(shù)據(jù)的狀態(tài),來維護(hù)UI的自動(dòng)更新,這就是 數(shù)據(jù)驅(qū)動(dòng)視圖(觀察者模式):每當(dāng)String的數(shù)據(jù)狀態(tài)發(fā)生變更,View層就能檢測(cè)并自動(dòng)執(zhí)行UI的更新,同理,每當(dāng)列表的數(shù)據(jù)源List<T>發(fā)生變更,RecyclerView也會(huì)自動(dòng)刷新列表。
MVVM的優(yōu)點(diǎn)顯而易見的是:雙向綁定技術(shù),當(dāng)Model變化時(shí),ViewModel會(huì)自動(dòng)更新,View也會(huì)自動(dòng)變化,能很好的做到數(shù)據(jù)一致性。View的功能有了進(jìn)一步的加強(qiáng),UI和業(yè)務(wù)邏輯解耦。但與此同時(shí),數(shù)據(jù)綁定使得 Bug 不易調(diào)試,也會(huì)使得一個(gè)位置的 Bug 被快速傳遞到別的位置。Google有出ViewModel等組件試圖規(guī)范MVVM在安卓開發(fā)中的書寫,初學(xué)者用起來上手快,但出于想學(xué)習(xí)架構(gòu)思想的目的,我認(rèn)為還是MVC和MVP更合適。
MVP
MVP對(duì)邏輯進(jìn)行了嚴(yán)格的提取,Presenter用于連接Model和View,負(fù)責(zé)所有邏輯處理(不僅限于表現(xiàn)邏輯,而是具體的業(yè)務(wù)邏輯)。
在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進(jìn)行的,所有的交互都發(fā)生在Presenter內(nèi)部,而在MVC中View會(huì)從直接Model中讀取數(shù)據(jù)而不是通過 Controller。Presenter就像View和Model的發(fā)言人(契合Presenter的字面義),它們相互之間是不可見的,只能通過Presenter來“傳話”。View向Presenter請(qǐng)求數(shù)據(jù),Presenter把數(shù)據(jù)送到Model,或者Presenter監(jiān)聽Model的數(shù)據(jù)變化,接收View層的動(dòng)作,通知View層的視圖發(fā)生變化。

Presenter完全把Model和View進(jìn)行了分離,主要的程序邏輯在Presenter里實(shí)現(xiàn),其中的View是很薄的一層,只應(yīng)該有簡(jiǎn)單的Set/Get的方法,用戶輸入和設(shè)置界面顯示的內(nèi)容,除此就不應(yīng)該有更多的內(nèi)容,絕不容許View直接訪問Model。而且,Presenter與具體的View是沒有直接關(guān)聯(lián)的,而是通過接口進(jìn)行交互,從而使得在變更View時(shí)候可以保持Presenter的不變,可以多次復(fù)用。
由此看出,MVP代碼解耦性應(yīng)該是最好的、而且代碼結(jié)構(gòu)清晰、可復(fù)用性高、擴(kuò)展性高,方便單元測(cè)試。
選型分析
因項(xiàng)目最終選型是MVP,下面主要比較一下MVVM和MVP、MVC和MVP,給出我選型的理由。
MVVM和MVP比較
MVVM的雙向綁定技術(shù)和數(shù)據(jù)狀態(tài)管理是它的技術(shù)亮點(diǎn),但這是把雙刃劍,帶來的問題如下:View和ViewModel之間界限不清,對(duì)初學(xué)者而言寫出結(jié)構(gòu)清晰的代碼較難;綁定帶來的就是View不夠靈活,復(fù)用性不高;而且綁定使得bug不易調(diào)試。我們項(xiàng)目對(duì)View和Model數(shù)據(jù)更新的需求不高,而且希望能寫出結(jié)構(gòu)規(guī)范、清晰的代碼,所以我們不選擇MVVM。
MVC和MVP比較
Android開發(fā)天然的就是MVC結(jié)構(gòu),Activity對(duì)應(yīng)了MVC中的V和C,隨著項(xiàng)目的深入,Activity處理的東西越來越多,代碼也越來越臃腫,而且在修改需求時(shí),因?yàn)閂和C的耦合性,即使是一個(gè)小小的View的改變,也要在Activity臃腫的代碼中找上半天,這對(duì)于程序員而言是件非常痛苦的事。
為了解決這種不必要的痛苦,提高開發(fā)效率,MVP把邏輯層抽出來成P層,Activity只充當(dāng)V的角色,業(yè)務(wù)邏輯控制交給了Presenter。要是遇到需求邏輯上的更改就可以只需要修改P層了或者遇到邏輯上的大改我們可以直接重寫一個(gè)P也可以,所以MVP模式對(duì)于APP來對(duì)控制邏輯和UI的解耦來說是一個(gè)不錯(cuò)的選擇,所以我們最終選擇的是MVP架構(gòu)模式。
上面貼的兩個(gè)鏈接對(duì)兩種模式的比較寫得非常清楚了,博主開發(fā)經(jīng)驗(yàn)豐富,也給出了MVP的demo,建議大家去學(xué)習(xí)一下。希望大家能有所收獲~~~