剖析幾種流行的 iOS 設計模式--MVC;MVVM;VIPER

在這篇文章里,我們爭取用最精簡的語言,解釋清楚這幾種設計模式到底給我?guī)砹耸裁幢憷?br>

以看圖說話的方式逐一解釋,最后總結(jié)

MVC

legacy MVC

這是我們最早接觸,也最熟悉的設計模式了

但要記住 Controller 不是我們通常理解的 ViewController !Controller 你可以認為是 Helper 方法。他不掌管 View 的生命周期。也就是說和 UIKit 無關(guān)!ViewController 你可以把他理解為 Scene 或 裝配中心。

感謝有人做了一個精辟的總結(jié)??磮D理解吧:


MVC

這才是真正的 MVC 使用姿勢。


MVP


MVP

從對比可以看到 MVC 的 Controller 變成了 Presenter ?, UIView 或 UIViewController 為 View 層。View 持有 Presenter,Presenter 持有 Model。View 與 Model 完全隔離。

當事件發(fā)生,交由 Presenter 進行業(yè)務邏輯處理,Presenter 從 Model 拿數(shù)據(jù),拿到數(shù)據(jù)后然后將數(shù)據(jù)返回給Presenter,Presenter 再返回給 View ??梢岳斫?Presenter 是一個中間人。

同樣 Presenter 應完全不依賴 UIKit 。如果需要與 View 交互,可以采用 Protocol 協(xié)議進行約定,調(diào)用。保證邏輯清楚,可測試。

最簡樣列代碼:

MVP Example

注意中文標注的地方。

另外還有一個 Supervising Presenter MVP 的升級版本,將 View 與 Model 進行綁定。View 會受到 Model 的變更影響,同時 Presenter 依舊可以控制 View 狀態(tài)。這種模糊的職責關(guān)系,還是少用為好。

MVVM


MVVM

MVP 一樣,View Model 承擔了類似 Presenter 中間層的角色。區(qū)別在于"數(shù)據(jù)與用戶行為"的綁定是在 View 與 View Model 層上發(fā)生的。這個時候不影響這個設計架構(gòu)中 View Model 應該承擔的角色屬性:更新 View 狀態(tài)。

關(guān)于綁定我們可以用 KVO 模式及函數(shù)式編程來實現(xiàn)我們的所需。如果你想更高效的完成這個動作,可以參考現(xiàn)有的解決方案:
? 1.? KVO : RZDataBinding or the SwiftBond
? 2.? Functional programming:? ReactiveCocoa, RxSwift or PromiseKit

不過,對于 ReactiveCocoa 我只能說慎用,設計起來會非常麻煩。

這里,我們還列舉最簡單的例子,沒有用到 KVO 或 RX 之類的設計,使用最為傳統(tǒng)的 Protocol 來實現(xiàn)彼此的交互過程


MVVM Example

我們可以看重點中文標注的地方,這里通過協(xié)議里的定義,第一步 View 層發(fā)起數(shù)據(jù)請求 showGreeting 交由 ViewModel 進行數(shù)據(jù)處理,處理完成后,因 greeting 發(fā)生變化,觸發(fā) greetingDidChange 事件發(fā)生。

在這個實例里 ViewController 有設定 greetingDidChange 回調(diào),所以實現(xiàn)了類似了上面所說的數(shù)據(jù)與行為綁定。

VIPER


VIPER

從結(jié)構(gòu)上來看,在 Presenter 中間多了一層 Interactor ,它主要起到了數(shù)據(jù)維護訪問的職責。你可以封裝更多的 Service 或 Managers 做為依賴調(diào)用。

對于頁面間的跳轉(zhuǎn),這里增加了 Router 層,專門用于跳轉(zhuǎn)邏輯,實際上現(xiàn)在不少架構(gòu)已經(jīng)加了各自的 Router 邏輯。這一點可能是從 Rails 框架繼承而來。

下面的例子不包含 Router 層

VIPER Example

從以上最簡的示例代碼來看,View 層 (ViewController) 同樣還是通過 ?Presenter 層 (GreetingViewEventHandler) 觸發(fā)事件邏輯,只不過 Presenter 拿數(shù)據(jù)是從 Iteractor 層(GreetingProvider)去拿。層與層之間還是通過協(xié)議通導,不依賴實體。

從這個架構(gòu)來看,它的耦合性是最小的,不過也帶了設計上的復雜性。所以使用時,要因地制宜。

總結(jié)

最后附上一位專家 Bohdan Orlov 的總結(jié),它們的橫向?qū)Ρ葓D,尋找自己最適合的模式使用。


iOS Arch comparison

耦合度 (Distribution)
可測性 (Testability)
易用性 (Ease of use)

PS:這里也提到了 Redux 模式,想了解 Redux 相關(guān)的內(nèi)容話,看這個鏈接吧。研究不深,大致是和 FP (函數(shù)式編程) 與 State 流相關(guān)。

總而言之

1. 沒有殺手锏
? ? no Sliver Bullet
2. 分層治理
? ? 分久必合,合久并分,看具體業(yè)務場景
4. 低耦合,高內(nèi)聚
? ? 基本要素
5. 遵從流行的框架與概念,有利于團隊間的溝通成本
? ? 如果一定要發(fā)明,請多推廣你的概念
6. 從簡到繁,再化繁為簡
? ? 前一個繁是業(yè)務的屬性,后一個繁是框架本身

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容