MVC架構模式
MVC是一種架構模式而非設計模式,GOF把MVC看作是3種設計模式:觀察者模式、政策模式與組合模式的合體,而核心是觀察者模式。
MVC架構模式圖
角色說明
模式說明
當使用者出發事件的時候,view層會發送指令到controller層,接着controller去通知model層更新資料,model層更新完資料以後直接顯示在view層上,這就是MVC的工作原理。
MVC(Model-View-Controller),它将應用程式劃分為三個部分:
- 模型Model: 資料塊(用于封裝與應用程式的業務邏輯相關的資料以及對資料的處理方法)
- 視圖View: 使用者界面
- 控制器Controller: 業務邏輯控制器(M和V之間的連接配接器,用于控制應用程式的流程,及頁面的業務邏輯)
優缺點
優點
- 子產品化了,将業務邏輯、資料處理與界面顯示進行分離
缺點
- View依賴特定的Model,無法元件化
- 主要業務邏輯都在Controller中,Controller會變得很重
- View和Controller緊耦合,如果脫離Controller,View難以獨立應用(功能太少)
在MVC裡,View是可以直接通路Model的!進而,View裡會包含Model資訊,不可避免的還要包括一些業務邏輯。 在MVC模型裡,更關注的Model的不變,而同時有多個對Model的不同View顯示。是以,在MVC模型裡,Model不依賴于View,但是View是依賴于Model的。不僅如此,因為有一些業務邏輯在View裡實作了,導緻要更改View也是比較困難的,至少那些業務邏輯是無法重用的。
MVP架構模式
MVP架構模式圖
角色說明
模式說明
MVP(Model-View-Presenter)跟MVC很相像,最大的差别是Model和View之間不進行通訊,都是通過Presenter完成。
Presenter與具體的View是沒有直接關聯的,而是通過定義好的接口進行互動,進而使得在變更View時候可以保持Presenter的不變,這樣就可以重用。Presenter與View的互動是通過接口來進行的。
View向Presenter發起調用請求,Presenter修改Model,Model修改完成後通知Presenter,Presenter再調用View的相關接口重新整理界面。這樣,View就不需要監聽具體Model的變化了,隻需要提供接口給Presenter調用就可以了。
優缺點
優點
- MVP模式會解除View與Model的耦合,有效的降低View的複雜性,我們可以修改視圖而不影響模型;同時又帶來了可擴充性、可測試性。
- 如果我們把邏輯放在Presenter中,那麼我們就可以脫離使用者接口來測試這些邏輯(單元測試)。
缺點
- 在不使用接口的情況下,視圖和Presenter的互動會過于頻繁,使得他們的聯系過于緊密。也就是說,一旦視圖變更了,presenter也要變更。
比較
MVC的耦合性還是較高的,View可以直接通路Model,導緻3者之間構成了回路。是以兩者的主要差別是,MVP中View不能直接通路Model,需要通過Presenter送出請求,View與Model不能直接通信。
MVVM架構模式
MVVM架構模式圖
模式說明
VM層:ViewModel,即 View的資料模型和Presenter的合體
ViewModel大緻上就是MVP的Presenter和MVC的Controller了,而View和ViewModel間沒有了MVP的界面接口,而是直接互動,用資料“綁定”的形式讓資料更新的事件不需要開發人員手動去編寫特殊用例,而是自動地雙向同步。資料綁定你可以認為是Observer模式或者是Publish/Subscribe模式,原理都是為了用一種統一的集中的方式實作頻繁需要被實作的資料更新問題。
MVVM與MVP非常相似,唯一差別是View和ViewModel進行雙向綁定,兩者之間有一方發生變化則會反應到另一方上。
優缺點
- 低耦合,視圖(View)可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的”View”上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
- 可重用性,可以把一些視圖邏輯放在一個ViewModel裡面,讓很多view重用這段視圖邏輯。
- 可測試,界面向來是比較難于測試的,而現在測試可以針對ViewModel來寫。
- 比起MVP,MVVM不僅簡化了業務與界面的依賴關系,還優化了資料頻繁更新的解決方案,甚至可以說提供了一種有效的解決模式。
DataBinding
DataBinding是谷歌官方釋出的一個架構,顧名思義即為資料綁定,是MVVM模式在Android上的一種實作,用于降低布局和邏輯的耦合性,使代碼邏輯更加清晰。DataBinding其實并沒有實作新的API來完成雙向綁定,隻是對原有API的封裝,如findViewById()和setText(),亦或是click事件,這些都被架構隐藏起來了。至于這些事件的觸發,例如View層接收到點選事件并通知ViewModel層,則是使用釋出訂閱模式實作的,如下圖:
DataBinding
每當View層更改時,ViewModel層通過訂閱收到通知;每當ViewModel層更改時,View層也會通過訂閱收到通知,這樣就實作了雙向綁定。
這裡可能會出現一個循環問題,假設其中某一層A改變,那麼另外一層B得到通知随之改變,這會導緻A層得到通知,A層也改變,循環往複出現問題。
DataBinding通過前後資料對比來決定是否更新,假設View層需要更新文本資訊(如TextView),則DataBinding會對比目前的文本和更新的文本,如果不一緻則進行更新操作;如果相同,則不做任何操作。其他的控件也有類似的判定操作,這樣就解決了資料雙向綁定中的循環問題。
三種模式出現的初衷
MVC模式的出現
為解決程式子產品化問題,于是MVC模式出現了:将業務邏輯、資料處理與界面顯示進行分離來組織代碼,即分成M、V、C層;
MVP模式的出現
但M、V層還是有互相交叉、隔離度不夠,于是出現了MVP: 隔離了MVC中的 M 與 V 的直接聯系,将M、V層更加隔離開來;
MVVM模式的出現
為了更加分離M、V層,于是出現了MVVM: 使得V和M層之間的耦合程度進一步降低,分離更為徹底。
差別
先說一下三者的共同點,也就是Model和View
- Model就是領域模型,資料對象,同時,提供外部對應用程式資料的操作的接口,也可能在資料變化時發出變更通知。Model不依賴于View的實作,隻要外部程式調用Model的接口就能夠實作對資料的增删改查。
- View就是UI層,提供對使用者的互動操作功能,包括UI展現代碼及一些相關的界面邏輯代碼。
三者的差異在于如何粘合View和Model,實作使用者的互動操作以及變更通知。M-V-X本質都是一樣的,重點還是在于M-V的橋梁,要靠X來牽線。
- Controller接收View的操作事件,根據事件不同,或者調用Model的接口進行資料操作,或者進行View的跳轉,進而也意味着一個Controller可以對應多個View。Controller對View的實作不太關心,隻會被動地接收,Model的資料變更不通過Controller直接通知View,通常View采用觀察者模式監聽Model的變化。
- Presenter,與Controller一樣,接收View的指令,對Model進行操作;與Controller不同的是Presenter會反作用于View,Model的變更通知首先被Presenter獲得,然後Presenter再去更新View。一個Presenter隻對應于一個View。根據Presenter和View對邏輯代碼分擔的程度不同,這種模式又有兩種情況:Passive View(被動視圖)和Supervisor Controller(監控員)。
- ViewModel,注意這裡的“Model”指的是View的Model,跟上面那個Model不是一回事。所謂View的Model就是包含View的一些資料屬性和操作的這麼一個東東,這種模式的關鍵技術就是資料綁定(data binding),View的變化會直接影響ViewModel,ViewModel的變化或者内容也會直接展現在View上。這種模式實際上是架構替應用開發者做了一些工作,開發者隻需要較少的代碼就能實作比較複雜的互動。
MVP和MVVM完全隔離了Model和View,但是在有些情況下,資料從Model到ViewModel或者Presenter的拷貝開銷很大,可能也會結合MVC的方式,Model直接通知View進行變更。在實際的應用中很有可能你已經在不知不覺中将幾種模式融合在一起,但是為了代碼的可擴充、可測試性,必須做到子產品的解耦,不相關的代碼不要放在一起。
分化是一種需求的必然結果,但卻沒有個一個确定的結果。MVC順着需求把UI相關的工作分化成了三份,這點經過實踐證明無可厚非。但是它們的三角關系卻被一些人認為帶來了一些問題,或者應該說他們有“更好的”解決方案。在MVC,當你有變化的時候你需要同時維護三個對象和三個互動,這顯然讓事情複雜化了。