MVC,MVP,MVVM设计模式的比较
1. MVC設(shè)計模式
1.1 概述
| M | Model,表示模型層,數(shù)據(jù)模型或業(yè)務(wù)模型,就是我們要顯示給用戶查看的內(nèi)容 |
| V | View,表示視圖層,就是用戶直接看到的界面,例如:Activity,Fragment,自定義View,還有XML布局文件 |
| C | Controler,表示控制層,用于模型和視圖間切換數(shù)據(jù),對應于Activity業(yè)務(wù)邏輯,數(shù)據(jù)處理和UI處理 |
而J2EE中的MVC分別表示:
- M:javabean
- V:jsp
- C:servlet
三角關(guān)系的問題就是維護問題。在MVC,當你有變化的時候你需要同時維護三個對象和三個交互,這顯然讓事情復雜化了
Android中經(jīng)常會出現(xiàn)數(shù)千行的Activity代碼,究其原因,Android中純粹作為View的各個XML視圖功能太弱,Activity基本上都是View和Controller的合體,既要負責視圖的顯示又要加入控制邏輯,承擔的功能過多,代碼量大也就不足為奇。所以更貼切的目前常規(guī)的開發(fā)說應該是View-Model 模式,大部分都是通過Activity的協(xié)調(diào),連接,和處理邏輯的
Activity中存在兩部分內(nèi)容:業(yè)務(wù)相關(guān)和界面相關(guān),V中的內(nèi)容較少,而C中的內(nèi)容較多
解決方案:將Activity中的業(yè)務(wù)部分拆分—-MVP,將Activity中的界面部分拆分—-MVVM
1.2 案例分析
Android中的ListView就用到了MVC設(shè)計模式
- M:數(shù)據(jù)的集合,List
- V:ListView
- C:Adapter,控制數(shù)據(jù)如何顯示在ListView上
而Activity控制層和視圖層都有
2. MVP設(shè)計模式
| Model | 依然是實體模型 |
| View | 對應于Activity和xml,負責View的繪制以及與用戶交互 |
| Presenter | 負責完成View于Model間的交互和業(yè)務(wù)邏輯 |
利用MVP的設(shè)計模型可以把部分的邏輯代碼從Fragment和Activity業(yè)務(wù)的邏輯移出來,在Presenter中持有View(Activity或者Fragment)的引用,然后在Presenter調(diào)用View暴露的接口對視圖進行操作,這樣有利于把視圖操作和業(yè)務(wù)邏輯分開來。MVP能夠讓Activity成為真正的View而不是View和Control的合體,Activity只做UI相關(guān)的事。但是這個模式還是存在一些不好的地方,比較如說:
Activity需要實現(xiàn)各種跟UI相關(guān)的接口,同時要在Activity中編寫大量的事件,然后在事件處理中調(diào)用presenter的業(yè)務(wù)處理方法,View和Presenter只是互相持有引用并互相做回調(diào),代碼不美觀。
這種模式中,程序的主角是UI,通過UI事件的觸發(fā)對數(shù)據(jù)進行處理,更新UI就要考慮線程的問題。而且UI改變后牽扯的邏輯耦合度太高,一旦控件更改(比較TextView 替換 EditText等)牽扯的更新UI的接口就必須得換。
復雜的業(yè)務(wù)同時會導致presenter層太大,代碼臃腫的問題。
切斷的View和Model的聯(lián)系,讓View只和Presenter(原Controller)交互,減少在需求變化中需要維護的對象的數(shù)量。MVP定義了Presenter和View之間的接口,讓一些可以根據(jù)已有的接口協(xié)議去各自分別獨立開發(fā),以此去解決界面需求變化頻繁的問題
MVP模式是MVC模式的一個演化版本,MVP全稱Model-View-Presenter。目前MVP在Android應用開發(fā)中越來越重要了。解耦view和model層
在Android中,業(yè)務(wù)邏輯和數(shù)據(jù)存取是緊緊耦合的,很多缺乏經(jīng)驗的開發(fā)者很可能會將各種各樣的業(yè)務(wù)邏輯塞進某個Activity、Fragment或者自定義View中,這樣會使得這些組件的單個類型臃腫不堪。如果不將具體的業(yè)務(wù)邏輯抽離出來,當UI變化時,你就需要去原來的View中抽離具體業(yè)務(wù)邏輯,這必然會很麻煩并且易出錯。
對于view層和presenter層的通信,我們是可以通過接口實現(xiàn)的,具體的意思就是說我們的activity,fragment可以去實現(xiàn)實現(xiàn)定義好的接口,而在對應的presenter中通過接口調(diào)用方法。
將activity中的業(yè)務(wù)部分拆分—mvp,使用接口實現(xiàn)view和presenter的通信和隔離,這種方式有一個缺點,就是接口會非常多
將activity中的界面相關(guān)內(nèi)容拆分—mvvm
2.1 使用MVP的好處
MVP模式會解除View與Model的耦合,有效的降低View的復雜性。同時又帶來了良好的可擴展性、可測試性,保證系統(tǒng)的整潔性和靈活性。
MVP模式可以分離顯示層與邏輯層,它們之間通過接口進行通信,降低耦合。理想化的MVP模式可以實現(xiàn)同一份邏輯代碼搭配不同的顯示界面,因為它們之間并不依賴于具體,而是依賴于抽象。這使得Presenter可以運用于任何實現(xiàn)了View邏輯接口的UI,使之具有更廣泛的適用性,保證了靈活度。
2.2 MVP模式的三個角色
- Presenter – 交互中間人
Presenter主要作為溝通View與Model的橋梁,它從Model層檢索數(shù)據(jù)后,返回給View層,使得View與Model之間沒有耦合,也將業(yè)務(wù)邏輯從View角色上抽離出來。負責完成View于Model間的交互和業(yè)務(wù)邏輯
- View – 用戶界面
View通常是指Activity、Fragment或者某個View控件,它含有一個Presenter成員變量。通常View需要實現(xiàn)一個邏輯接口,將View上的操作轉(zhuǎn)交給Presenter進行實現(xiàn),最后,Presenter 調(diào)用View邏輯接口將結(jié)果返回給View元素。對應于Activity和xml,負責View的繪制以及與用戶交互
- Model – 數(shù)據(jù)的存取
Model 角色主要是提供數(shù)據(jù)的存取功能。Presenter 需要通過Model層存儲、獲取數(shù)據(jù),Model就像一個數(shù)據(jù)倉庫。更直白的說,Model是封裝了數(shù)據(jù)庫DAO或者網(wǎng)絡(luò)獲取數(shù)據(jù)的角色,或者兩種數(shù)據(jù)方式獲取的集合。
3. MVVM設(shè)計模式
| Model | 實體模型,代表基本業(yè)務(wù)邏輯 |
| View | 對應于Activity和xml,負責View的繪制以及與用戶交互 |
| ViewModel | 將view和model聯(lián)系在一起,起到橋梁的作用,負責完成View于Model間的交互,負責業(yè)務(wù)邏輯 |
MVVM的目標和思想MVP類似,利用數(shù)據(jù)綁定(Data Binding)、依賴屬性(Dependency Property)、命令(Command)、路由事件(Routed Event)等新特性,打造了一個更加靈活高效的架構(gòu)。
ViewModel大致上就是MVP的Presenter和MVC的Controller了,而View和ViewModel間沒有了MVP的界面接口,而是直接交互,用數(shù)據(jù)“綁定”的形式讓數(shù)據(jù)更新的事件不需要開發(fā)人員手動去編寫特殊用例,而是自動地雙向同步。比起MVP,MVVM不僅簡化了業(yè)務(wù)與界面的依賴關(guān)系,還優(yōu)化了數(shù)據(jù)頻繁更新的解決方案,甚至可以說提供了一種有效的解決模式。
可以直接在layout布局xml中綁定數(shù)據(jù),分離視圖與業(yè)務(wù)邏輯,低耦合,可重用,獨立開發(fā),可測試
View的變化可以自動的反應在ViewModel,ViewModel的數(shù)據(jù)變化也會自動反應到View上,data binding框架解決了數(shù)據(jù)綁定的問題
- 數(shù)據(jù)驅(qū)動
在MVVM中,以前開發(fā)模式中必須先處理業(yè)務(wù)數(shù)據(jù),然后根據(jù)的數(shù)據(jù)變化,去獲取UI的引用然后更新UI,也是通過UI來獲取用戶輸入,而在MVVM中,數(shù)據(jù)和業(yè)務(wù)邏輯處于一個獨立的View Model中,ViewModel只要關(guān)注數(shù)據(jù)和業(yè)務(wù)邏輯,不需要和UI或者控件打交道。由數(shù)據(jù)自動去驅(qū)動UI去自動更新UI,UI的改變又同時自動反饋到數(shù)據(jù),數(shù)據(jù)成為主導因素,這樣使得在業(yè)務(wù)邏輯處理只要關(guān)心數(shù)據(jù),方便而且簡單很多。
- 低耦合度
MVVM模式中,數(shù)據(jù)是獨立于UI的,ViewModel只負責處理和提供數(shù)據(jù),UI想怎么處理數(shù)據(jù)都由UI自己決定,ViewModel 不涉及任何和UI相關(guān)的事也不持有UI控件的引用,即使控件改變(TextView 換成 EditText)ViewModel 幾乎不需要更改任何代碼,專注自己的數(shù)據(jù)處理就可以了,如果是MVP遇到UI更改,就可能需要改變獲取UI的方式,改變更新UI的接口,改變從UI上獲取輸入的代碼,可能還需要更改訪問UI對象的屬性代碼等等。
- 更新 UI
在MVVM中,我們可以在工作線程中直接修改View Model的數(shù)據(jù)(只要數(shù)據(jù)是線程安全的),剩下的數(shù)據(jù)綁定框架幫你搞定,很多事情都不需要你去關(guān)心。
- 團隊協(xié)作
MVVM的分工是非常明顯的,由于View和View Model之間是松散耦合的。一個是處理業(yè)務(wù)和數(shù)據(jù),一個是專門的UI處理。完全有兩個人分工來做,一個做UI(xml 和 Activity)一個寫ViewModel,效率更高。
- 可復用性
一個View Model復用到多個View中,同樣的一份數(shù)據(jù),用不同的UI去做展示,對于版本迭代頻繁的UI改動,只要更換View層就行,對于如果想在UI上的做AbTest 更是方便的多。
- 單元測試
View Model里面是數(shù)據(jù)和業(yè)務(wù)邏輯,View中關(guān)注的是UI,這樣的做測試是很方便的,完全沒有彼此的依賴,不管是UI的單元測試還是業(yè)務(wù)邏輯的單元測試,都是低耦合的。
通過上面對MVVM的簡述和其他兩種模式的對比,我們發(fā)現(xiàn)MVVM對比MVC和MVP來說還是存在比較大的優(yōu)勢,雖然目前Android開發(fā)中可能真正在使用MVVM的很少.
通過一系列的學習,消化和參考。目前,MVC,MVP都已經(jīng)應用到項目開發(fā)中了。
關(guān)于MVVM目前是只聞其聲,不見其下樓。MVVM算是舶來品,從Web前端的Argular而來。Argular有個databind的屬性領(lǐng)我們羨慕不已,瞬間感覺高大上啊!
其實,還有WPF,這個落寞巨人微軟的背影。這個有個點感覺很牛逼就是,界面開發(fā)和業(yè)務(wù)開發(fā)完全分開實現(xiàn)。界面開發(fā)除了數(shù)據(jù)是假的,業(yè)務(wù)操作綁定,顯示全是真的,業(yè)務(wù)流程的定義和界面設(shè)計進行了解耦,二者通過接口文檔,默認命名規(guī)則進行約定實現(xiàn)。最后界面顯示和業(yè)務(wù)處理拼合起來就好了。
我覺得除了databind (現(xiàn)在有robobinding可以參考),還需要 有事件訂閱與發(fā)布 的模塊(推薦使用使用facebook的flux),相關(guān)技術(shù)用到RxJava,RxAndroid的模塊。
而后再加上代碼自動生成,通過web服務(wù)器的數(shù)據(jù)庫,直接生成業(yè)務(wù)處理代碼與接口,Android端也自動生成業(yè)務(wù)處理類。著多牛逼啊,然后Android開發(fā)失業(yè)。web開發(fā)失業(yè)。數(shù)據(jù)庫設(shè)計和界面開發(fā)笑到了最后。
這都是我們對于mvvm的自嗨和幻想+YY,Google大兄弟目前還沒有推薦的技術(shù)實現(xiàn)。感覺Google處境很尷尬,現(xiàn)在Facebook 推出的 React Native 如日中天,大有替代Java 原生編程的趨勢。如果真取代了,Android Application 將是 Node.js JavaScript的樂園。我們原生應用的開發(fā)工程師可要下崗了。目前已經(jīng)在不斷蠶食Android原生開發(fā)的份額,通過Cordova這個內(nèi)奸,Html5家族由原來的jQuery Mobile 到 Augular.js 和ionic,再到 React 和 React Native,來勢洶洶。JS是如日中天,蓬勃發(fā)展。再回來討論MVVM竟然是前端帶來的技術(shù)。遇見的未來競爭會更激烈。廣大Android原生開發(fā)的從業(yè)者受的的沖擊會更大。
總結(jié)
以上是生活随笔為你收集整理的MVC,MVP,MVVM设计模式的比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Data Binding Library
- 下一篇: C/C++在Android开发中的应用