我們開發軟體中應用各種模式,主要是為了 1. 職責劃分:一個類只做一件事 2. 易用,可維護,方便擴展 3. 解耦,相互獨立,可單獨測試 各種設計模式其實都是在解決上面的問題,讓我們對比看看吧。 一、如何理解MVC設計模式 在通常的定義中,MVC 是下圖的結構 但是在 cocoa 體系中,蘋果建議的 ...
我們開發軟體中應用各種模式,主要是為了
- 職責劃分:一個類只做一件事
- 易用,可維護,方便擴展
- 解耦,相互獨立,可單獨測試
各種設計模式其實都是在解決上面的問題,讓我們對比看看吧。
一、如何理解MVC設計模式
在通常的定義中,MVC 是下圖的結構
但是在 cocoa 體系中,蘋果建議的 MVC 模式如下圖所示
在斯坦福課程中,解釋的 MVC 如下圖所示
綜合一下在 cocoa 系統中可以這麼理解:
- M model,存儲、定義、操縱數據
- V view,用戶看到的UI,能夠和用戶交互
- C controller,協調者,把 model 的數據放到 view 中展示,相應 view 的交互改變 model
特別在 cocoa 系統中
C 持有一個 model,直接操作 model;model 通過 KVO、通知等方式拋出自己改變的事件
C 通過 IBOutlet 或者直接持有一個 view,他可以直接操作這個view;view 有了交互,可以通過action target 方式 以及 delegate 方式 讓 controller 來響應事件,但是 view 並不知道具體是哪個類對象;view 的需要的數據,可以通過 protocol 的方式,讓 controller 實現這個 protocol 並且成為 view 的數據源,來提供數據給 view,view並不需要知道 controller 的具體的類對象。
最簡單的例子就是 UITableviewController,他一般會持有一個 NSArray 作為 model,同時根視圖就是一個 UITableView,這是 view。controller 從網路或者本地載入數據賦值給 array,然後 reload tableview。tableview 繪製時請求數據源,相應用戶事件會通過delegate 發起調用。tableview 與 array 並沒有直接的關係。
進一步的,如果我的頁面很複雜,那麼這個 MVC 是怎麼處理的呢?看看斯坦福的另一張講義:
也就是 cocoa 中,Controlelr 控制的 view 可以是屬於別的 MVC 中的,最外層的 MVC 來管理這些子 MVC。所以最好不要一個 C 中對應多個 view 或者 model,而是需要拆分成多個 MVC 來。
缺點:
- 如果嚴格按照MVC模式的話,不像 view 傳遞 model,那麼代碼就會臃腫,想象往一個cell 設置用戶信息,單獨傳一個 userModel,然後 cell 內部處理會很簡潔,如果分開在controller 裡面傳 頭像、姓名、簽名,就會很臃腫
- view 和 controller 一般都是綁定在一起的,生命周期的控制依賴於 controller,獨立測試會很不方便
二、MVP 模式
基於 MVC 的缺點和優點,既然 view 和 cocoa 中的 viewController 已經那麼強的緊密耦合了,那麼把這兩者看成同一個東西,一起做為一個 view 。
Model 層負責數據的增刪改查(網路,資料庫查詢,本地文件讀寫)。
Presenter 層只是一個中介,負責數據的轉發。
上圖展示的是 View 持有 Presenter,Presenter 持有 Model。所以 Presenter 不依賴於具體的 View,這個可以通過 Protocol 來實現,讓 View 實現一些數據更新的協議,presenter 就可以不知道View 具體是什麼就能傳遞數據。
優點:
每一層的任務互相獨立分開了,讓測試更加方便。
** 缺點:**
代碼量會提升很多。
示例見參考2.參考2的複雜MVP可以簡化如下圖所示:
三、MVVM 模式
MVP 的 Presenter 需要主動更新 view,如果增加一個綁定機制呢,model 的改變及時反饋在 view上會不會更酷。但是這樣就會讓 model 和 view 關聯起來,所以就出來一個 viewModel 的東西。
ViewModel 持有 Model,管理 Model 並可以把 Model 中的數據處理成 View 需要的數據。同時可以處理用戶輸入驗證邏輯,視圖顯示邏輯,發起網路請求和其他各種各樣的代碼。
View 持有 ViewModel,並且和 ViewModel 中的數據綁定,讓 ViewModel 中的數據改變及時反應在 View上;並且把一些按鈕事件的 target 設置給 ViewModel。
優點:
- View Model 的引入配合狀態流和響應式編程使得 App 的結構更加清晰,交互更加流暢。
- MVVM 中的 View 責任多一點,因為要設置綁定,但也因為綁定,所以代碼量更少。測試時主要是測試 View Model 和 Model 。
缺點:
因為數據的雙向綁定,讓BUG的定位更加困難,過大的項目也會耗費更多的記憶體。
四、VIPER 模式
VIPER 其實是 MVP 的一種擴展,VP不變,M變成了 Interactor 和 Entity,外加一個 Routing。Entity 就是 model 的數據結構, Interactor 就是處理 model 的類,增刪改查model,Routing 就是控制視圖的跳轉。可以看到 viper 模式分的更細,每層的功能更明確,更容易測試。但是也更複雜,代碼量也會更加龐大。
可以參考下麵兩個圖結構圖。
圖一:
圖二:
參考1.https://www.objc.io/issues/13-architecture/mvvm/
參考2.https://github.com/amacou/MVPExample
參考3.https://www.objc.io/issues/13-architecture/viper/