關於MV(X)系列的架構模式的討論從最初的MVC提出到如今的MVVM都沒間斷過(VIPER架構模式不作討論),不一樣人對架構模式持有不一樣的觀點,關於架構模式的博客也不少。從接觸MVC開始,再到後面實際的運用,總會存在不少疑問,在面試中也被問倒了,面試官的話深深的觸及個人靈魂,痛定思痛,專門花時間去深刻了解這方面的知識。如今對於MV(X)系列的架構模式本人也有本身的見解,寫這篇博客除與發表觀點,同時算是一次總結。在補充下,文章更多的是從iOS開發角度出發去思考。html
MVC模式最先由Trygve Reenskaug在1978年提出,是施樂帕羅奧多研究中心(Xerox PARC)在20世紀80年代爲程序語言Smalltalk發明的一種軟件架構。MVC模式的目的是實現一種動態的程序設計,使後續對程序的修改和擴展簡化,而且使程序某一部分的重複利用成爲可能。——維基百科前端
MVC模式根據程序中的對象的職責或功能進行分類,分爲三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。MVC是一種複合模式,由多個基本的設計模式組合成。這也是MVC會被稱爲設計模式的緣由。除了對程序中對象的分類,還規定了它們通訊的方式。面試
V:負責UI展現和事件交互處理設計模式
M:數據存儲和數據的處理網絡
C:負責V和M的通訊,管理V和M的生命週期。架構
來看下傳統MVC的架構圖(引用蘋果的圖): app
從這個圖中能夠看到MVC是由策略模式,組合模式,觀察者模式組合而成混合模式。View是以組合模式實現的,在iOS中把繼承至UIResponder的類做爲事件的響應者經過樹形結構組合起來,用來表示部分以及總體層次。Controller是View的一個策略,View能夠加載在不一樣的Controller上。View在Model上註冊爲觀察者,Model數據變動時,View能夠監聽到Model變動的通知。當View接收到用戶事件時,將事件處理移交至Controller。Controller接收事件後能夠請求Model進行數據變動或者請求View去更改行爲或者外觀。當Model的數據變動的時候,Model通知全部註冊的觀察者,View收到數據變動通知後,更新View外觀。函數
在這種模式下,Controller是View的一個策略,同時還負責View的事件處理,還要負責通知Model更新數據。不一樣的View事件不一樣,不一樣的Model數據更新的接口也不一樣,在這種狀況下,Controller是很難複用的。能複用的模塊只有是View和Model。但從上圖中能夠看到View和Model存在耦合,View和Model沒有徹底隔離。View的更新依賴於Model。爲了達到複用的目的,View的更新不該該依賴於Model,應該獨立於Controller和Model,同理Model也是獨立於Controller和View的。接下來咱們看下蘋果理想的MVC模式。oop
蘋果理想的MVC,就是將View和Model徹底隔離,View和Model之間不存在耦合,View和Model經過Controller這個中介者進行雙方通訊。在這裏Controller是中介者模式的一種實現。View在這裏也是命令模式的實現,經過Target-action機制,能夠將View做爲命令的執行者,對應Target。action就是一個的命令。響應鏈是調度者,負責給合適的執行者下發命令。測試
蘋果理想的MVC架構圖:
在iOS裏面咱們知道有個UIViewController類,ViewController的出現源自蘋果爲了提升開發效率將View和Controller綁定到一塊兒。從實際的使用上能夠感受到開發效率獲得提升。對於新手快速入門也很方面,由於不須要去考慮任何架構模式,不用去嚴格的作不一樣對象的職責區分,大多數的初學者仍是較習慣於大雜燴式的程序撰寫,因此致使Massive Controller的出現。ViewController作的事就變得複雜,負責View和Model的生命週期,負責View和Model的通訊。負責頁面跳轉,負責網絡請求,負責處理數據等。這已經違反了設計模式的單一性原則。隨着業務增多項目會變得難以維護。
iOS中的MVC架構圖:
即使蘋果如此設計,咱們仍是能夠實現蘋果理想的MVC。咱們須要對ViewController進行瘦身。View的職責不變。業務邏輯抽離到Model中,ViewController中負責View和Model的生命週期,負責View和Model的通訊,負責頁面跳轉。View將事件處理委託給ViewController,並對外提供更新UI的接口。ViewController,Model處理髮起網絡請求,處理數據完後通知ViewController。而後ViewController在去更新View。這樣保持View和Model的隔離,達到易複用和易測試的效果,同時減輕了ViewController的負擔。當業務增多的時候能夠添加多個MVC對業務進行劃分,避免講業務代碼都寫在同一個MVC代碼中。
MVC設計提出是爲了實現一種動態的程序設計,使後續對程序的修改和擴展簡化,而且使程序某一部分的重複利用成爲可能,MVC有助於應用程序長遠的發展,可擴展性、可維護性和可測試性由於 MVC 的特性而變得容易,MVC對程序中的對象進行了劃分,能夠對View和Model進行復用。
可是MVC的缺點也很明顯,傳統的MVC中只有Model能夠複用,View更新依賴於Model,View沒有獨立於Model和Controller,複用可能性小。Controller做爲View和Model通訊的通道,處理View提交的事件,同時負責通知Model更新數據等,Controller定製性太高自己就很難複用。從測試角度來講業務邏輯都放在Controller中就很難測試。在來講說蘋果理想的MVC,這種模式下,Controller也是沒法複用的,View和Model的複用性高。測試角度View和Model對外提供了接口,能夠經過測試接口判斷邏輯和界面更新是否正確。同時Controller須要手動實現View的更新的代碼和各類事件代理通訊方法。
在具體的實現中Presenter會持有View的弱引用,不負責管理View生命週期,當Model通知Presenter數據發生變動後,Presenter就能夠更新View。爲了達到結構的目的,讓Presenter不依賴於View,一般結合業務界面定製一個View的協議,抽象出界面更新的方法,而後Presenter持有這個協議的引用,就不用依賴於具體的View。這點是符合設計模式的依賴倒置原則的。同時也能夠結合業務抽象出Presenter的行爲協議,能夠切換不一樣的Presenter實現。這裏的View是一種策略,Presenter也是一種策略,涉及的是策略設計模式。
使用Passive View或Supervising Controller的決定主要取決於你但願應用程序的可測試性。若是須要可測試性高,使用Passive View是最合適的,能夠經過測試Presenter測試全部的UI邏輯。若是但願代碼簡潔而不徹底可測試,選擇SuperVising,能夠減小編寫Presenter中UI更新的代碼。
在MVVM以前得先說下MVVM的發展歷史,MVVM是馬丁·福勒的PM(Presentation Model)架構模式的變體。MVVM和PM都來自MVC模式。MVVM由微軟架構師Ken Cooper和Ted Peters開發,經過利用WPF(微軟.NET圖形系統)和Silverlight(WPF的互聯網應用派生品)的特性來簡化用戶界面的事件驅動程序設計。MVVM也被稱爲model-view-binder。
PM 模式與 MVP 比較類似,它從視圖層中分離了行爲和狀態,PM以不依賴於特定用戶界面平臺的方式抽象出視圖(建立了視圖模型),MVVM以相同的方式抽象出視圖的狀態和行爲。抽象出視圖和咱們上面提到的以協議的方式定義個視圖模型是一個道理。和Presenter不一樣的是PM 模式將視圖中的所有狀態和行爲放到一個單獨的展現模型中(PM),協調Model而且爲視圖層提供一個接口。換句說PM 經過引入展現模型將模型層中的數據與複雜的業務邏輯封裝成屬性與簡單的數據同時暴露給視圖,讓視圖和展現模型中的屬性進行同步。
MVVM模式經過Binder層對View和VM完成雙向綁定減小手動更新View的代碼編寫,同時達到View和Model的分離的效果,讓它們各司其職。在iOS中Binder層的實現能夠經過RAC實現。同時MVVM存在缺點,MVVM的創造者表示實現MVVM的開銷對於簡單的UI操做是「過分的」,很是大的應用程序中的數據綁定會致使至關大的內存消耗。
從MVC到MVVM,MV(X)系列的架構模式本質上都是從MVC上演化出來的,對程序的對象進行職責區分,減小View和Model之間的耦合提升它們的複用性,爲了可測試性能夠作進一步的優化。對於不一樣的架構模式的選擇要根據適合開發平臺的模式,蘋果推薦使用MVC,安卓使用MVP,前端使用MVVM。固然能夠根據項目需求考慮選擇更適合的設計模式。不管選擇什麼架構模式,我以爲都要對這些架構模式有所瞭解,這樣才能寫出更好的項目。
參考文章