一千個程序員眼中有一千種 MVC
SmallTalk MVC
Models
- Models 表示知識炉奴。
- 一個 Model 可以是單個對象桨吊,也可以是一些對象的組合結(jié)構(gòu)。
- Model 和它的部件之間可能有一對一的通信认烁。
- 對 Model 的所有者(View)來說总滩,它如實地反映了真實世界。
- Model 是問題的一個可標示部分幸逆。
- 某個 Model 的所有節(jié)點都應(yīng)該處在同樣的問題等級棍辕,將面向問題的節(jié)點(如日歷中的預(yù)約)和實現(xiàn)細節(jié)(如圖形)混在一起是不好的暮现。
Views:
- View 是它的 Model 的(可見)表示。
- 它會重點關(guān)注 Model 中的某些屬性而忽視其它的楚昭,因此它也是一個展示過濾器栖袋。
- View 和它的 Model(或者 Model 的一部分)連接。它以問問題的方式得到展示所需的數(shù)據(jù)抚太,發(fā)送合適的消息來更新 Model塘幅。所有這些問題和消息都在 Model 的術(shù)語中,因此 View 必須知道它所展示的 Model 的屬性的語義尿贫。
Controllers
- Controller 是用戶和系統(tǒng)的橋梁电媳。
- 它指定相關(guān)的 Views 讓它們將自己展示在屏幕的適當位置。
- 它通過菜單或者其它可以支持命令和數(shù)據(jù)的形式來表示用戶的意圖庆亡。
- Controller 不應(yīng)該去補充 Views匾乓,比如它不會在幾個 View 之間繪制箭頭把它們連接起來。
- View 永遠不會知道用戶的輸入又谋,譬如鼠標操作和鍵盤點擊拼缝。在 Controller 可以寫一個方法向 View 發(fā)送消息,它可以精確模擬用戶的一系列指令搂根。
Editors
- 一個 Controller 和它所有的 Views 相關(guān)聯(lián)珍促,它們被稱為 Controller 的部件。
- 某些 Views 提供一種特殊的 Controller——Editor剩愧。
- Editor 允許用戶修改 View 所展示的信息猪叙。
- 這樣的 Editor 可能被插入 Controller 和 View 之間,它表現(xiàn)得像 Controller 的一個擴展仁卷。
- 一旦編輯操作結(jié)束穴翩,Editor 被移除。
- Editor 通過它所連接的 View 的 metaphors(隱喻锦积,象征)來和用戶交流芒帕,因此 Editor 和 View 是強關(guān)聯(lián)的。
- Controller 只能向 View 請求從而得到一個 Editor 的引用丰介,別無他法背蟆。
觀點
以上是對 MVC 原始論文的整理翻譯。
在 MVC 中,V 可以和 C 通信,V 可以和 M 通信鹃共。
最早的 MVC 于 1979 年提出,當時還需要程序員全權(quán)處理用戶輸入——Controller 的職責(zé)垛叨。而現(xiàn)在,大部分事情已經(jīng)被操作系統(tǒng)做了柜某,我們已經(jīng)做不到“View 永遠不會知道用戶的輸入”嗽元,我們也不太需要 Editor敛纲,因為這些已經(jīng)被封裝進UITextField
之類的控件中,View 本身就具備一定的交互功能剂癌。用戶操作往往被封裝成“事件”傳遞給 View淤翔。
所以真正的 MVC 是一種過時的架構(gòu)。
Apple MVC
Model Objects
Model Objects 包括應(yīng)用所需的數(shù)據(jù)佩谷,并且定義數(shù)據(jù)處理的邏輯办铡。
Model 和 View 之間不該有明確的關(guān)聯(lián)。
用戶在 View 層的操作會通過 Controller 增加或改變 Model琳要。
Model 一旦改變(譬如從網(wǎng)絡(luò)獲取了新數(shù)據(jù)),它會通知 Controller秤茅,Controller 再去更新 View稚补。
View Objects
View Object 是應(yīng)用中用戶可以看到的部分。
View 知道如何繪制自己框喳,可以響應(yīng)用戶操作课幕。
View 展示 Model 中的數(shù)據(jù),并且允許編輯這些數(shù)據(jù)五垮。盡管如此乍惊,View 和 Model 是完全解耦的。
View 通過 Controller 得知 Model 中數(shù)據(jù)的變化放仗;并且將用戶發(fā)起的變化通過 Controller 反映到 Model润绎。
Controller Objects
Controller 是 View 和 Model 之間的中間人。
Controller 也可以用來設(shè)置和協(xié)調(diào)應(yīng)用的任務(wù)诞挨、管理其它對象的生命周期莉撇。
Controller 會將 View 層的變化反映到 Model 層,也會將 Model 層的變化反映到 View 層顯示出來惶傻。
觀點
Apple 所謂的 MVC 跟原始的 MVC 基本已經(jīng)毫無關(guān)系……在這里 C 成了一個中介者棍郎,用以協(xié)調(diào) V 和 M。
這個模式其實沒有特別大的問題银室,但是由于 Cocoa 中的 ViewController 還承擔了 View Container 的工作涂佃,我們在日常開發(fā)中又容易把 Model 層設(shè)計得過于單薄(比如只是一個單純的數(shù)據(jù)對象)蜈敢,從而導(dǎo)致 Controller 中有大量本該放在 View 和 Model 中的代碼辜荠。
所以這是一個最容易被濫用的模式。
MVVM
ViewModel
- 一個抽象的視圖(AbstractView)扶认。
- 包含概念:視圖狀態(tài)(ViewState)侨拦、數(shù)據(jù)轉(zhuǎn)換器(ValueConversion)、操作 Model/ViewModel 的指令辐宾。
數(shù)據(jù)綁定
- 需要一種綁定機制將 View 和 ViewModel 連接起來(View 和 ViewModel 可以用不同語言編寫)狱从。
觀點
MVVM 由微軟架構(gòu)師 John Gossman 于 1996 年提出膨蛮,在提出這個概念以前,他們團隊早已在實踐這個架構(gòu)了季研。由于 MVVM 是 MVC 的一種改進敞葛,M 和 V 部分和 MVC 是類似的。而 Gossman 認為在現(xiàn)代 GUI 系統(tǒng)中与涡,C 的大部分工作已經(jīng)由系統(tǒng)幫你做了惹谐,所以 C 并沒有被拋棄,而是隱藏到幕后了驼卖。
MVVM 中的 VM 承擔了狀態(tài)管理氨肌、數(shù)據(jù)轉(zhuǎn)換、操作處理之類的任務(wù)酌畜,它早先被用于 WPF(View 層由 XMAL 編寫怎囚,且內(nèi)建了綁定機制),但寫 WPF 并不一定要用 MVVM桥胞,你完全可以將 View 和 Model 直接綁定——如果你的程序足夠簡單恳守。
由于在 iOS 中并沒有一個內(nèi)建的綁定機制,很多人覺得在項目中多一層數(shù)據(jù)轉(zhuǎn)換層就是 MVVM 了贩虾,這有一些片面催烘。我還是覺得真的要用 MVVM 就必須建立一套綁定機制,可以利用 RxSwift 和 RAC 之類的第三方庫缎罢,或者自己擼一套伊群。
MVP
1996年,Mike Potel 在一篇論文中提出 Model-View-Presenter 的概念策精。這個時候的 View 已經(jīng)跟 MVC 剛誕生時的 View 全然不同了在岂,它可以接受用戶輸入。MVP 的主要思想是用戶輸入由 V 流進蛮寂,V 通過 P 更新 M蔽午,同時 V 跟 M 之間還是跟 MVC 中一樣,V 可以調(diào)用 M 的接口酬蹋,M 通過觀察者模式向 V 廣播自身的更新及老。
同 MVC 一樣,而今的 MVP 與最早的 MVP 也相距甚遠》蹲ィ現(xiàn)在為人所普遍接受的 MVP 是骄恶,V 和 M 完全解耦,通過 P 進行通訊匕垫。但和 Apple MVC 不同的是僧鲁,P 并不包含生命周期控制之類的職責(zé),而且一般是由 V 去持有 P。
觀點
MVP 似乎在 Android 開發(fā)中比較流行寞秃,我沒有實踐過斟叼,不敢妄言。
VIPER
由 View春寿、Interactor朗涩、Presenter、Entity绑改、Router 組成谢床。
觀點
同樣沒有實踐過……但直觀上感覺是把 MVP 進行了進一步拆分——Presenter 拆為 Presenter 和 Router,Model 拆為 Interactor 和 Entity厘线。
小結(jié)
對于結(jié)構(gòu)劃分识腿,還是要根據(jù)項目規(guī)模來,規(guī)模大就分層細一點造壮,規(guī)模小就粗一點覆履。因為分層越多,層與層之間的通信成本就越高费薄。通信方面可以采取各種手段——接口調(diào)用、觀察監(jiān)聽栖雾、數(shù)據(jù)綁定等楞抡。
我個人比較傾向于分為 View、Model析藕、ViewModel召廷、Router 這幾層,以數(shù)據(jù)綁定為基礎(chǔ)進行通信账胧。
各個層最好都定義一個協(xié)議來確認各自的職責(zé)竞慢,可以有一些默認實現(xiàn)。