現(xiàn)在我們面對架構(gòu)設(shè)計模式的時候有了很多選擇:
- MVC
- MVP
- MVVM
- VIPER
首先前三種模式都是把所有的實(shí)體歸類到了下面三種分類中的一種:
- Models(模型)數(shù)據(jù)層,或者負(fù)責(zé)處理數(shù)據(jù)的 數(shù)據(jù)接口層厘熟。
- Views(視圖)展示層(GUI)屯蹦。對于 iOS理論上來來說所有以 UI 開頭的類基本都屬于這層。
- Controller/Presenter/ViewModel(控制器/展示器/視圖模型)
它是 Model 和 View 之間的膠水或者說是中間人绳姨。
一般來說登澜,當(dāng)用戶對 View 有操作時它負(fù)責(zé)去修改相應(yīng) Model;當(dāng) Model 的值發(fā)生變化時它負(fù)責(zé)去更新對應(yīng) View飘庄。
demo在最下面
一脑蠕、MVC
??MVC是模型 (model)-視圖 (view)-控制器 (controller) 的縮寫。它表示的是一種常見的客戶端軟件開發(fā)框架跪削。
(1)首先看看MVC它原來的樣子
??經(jīng)典MVC模式在提出時谴仙,大致是上圖這樣的。在這種架構(gòu)下碾盐,View 是沒有狀態(tài)的晃跺,在Model變化的時候它只是簡單的被 Controller重繪,盡管這種架構(gòu)可以在應(yīng)用里面實(shí)現(xiàn)毫玖,但是由于 MVC 的三種實(shí)體被緊密耦合著掀虎,每一種實(shí)體都和其他兩種有著聯(lián)系,所以即便是實(shí)現(xiàn)了也沒有什么意義孕豹。
(2)理想化的MVC,也就是蘋果的MVC
View 和 Model 之間是相互獨(dú)立的十气,它們只通過 Controller 來來負(fù)責(zé)二者的交互励背。這樣的設(shè)計,使得View 和 Model 直接解耦合了砸西。
(3)現(xiàn)實(shí)中的MVC
??MVC 鼓勵編寫大規(guī)模的視圖控制器叶眉,因為 View 的整個生命周期都需要它去管理址儒,Controller 和 View 很難做到相互獨(dú)立。
??雖然你仍有能力將一些業(yè)務(wù)邏輯和數(shù)據(jù)轉(zhuǎn)換成Model衅疙,但你沒辦法將View從Controller中分離莲趣。在大多數(shù)情況下,View的責(zé)任是把事件傳遞給Controller饱溢。
Controller最終演變成一個其他人的delegate和data source喧伞,甚至還負(fù)責(zé)網(wǎng)絡(luò)請求的發(fā)起和取消,另一方面Controller負(fù)責(zé)了界面跳轉(zhuǎn)的操作绩郎,界面跳轉(zhuǎn)的相關(guān)配置是直接在對應(yīng)的Controller實(shí)例上設(shè)置的潘鲫,這樣就很容易把源界面和目的界面耦合起來,表現(xiàn)在導(dǎo)入很多其他頭文件肋杖。最后變得臃腫不堪溉仑,所以又稱之為Massive View Controller(大量的視圖控制器)。
在許多情況下状植,你見到的代碼類似于這樣:
cell.model = self.dataArray[indexPath.row];
Model和View經(jīng)常會直接通信浊竟,產(chǎn)生了耦合。
二津畸、MVP
??MVC的缺點(diǎn)在于并沒有區(qū)分
業(yè)務(wù)邏輯和業(yè)務(wù)展示
振定,這對單元測試很不友好。
??MVP針對以上缺點(diǎn)做了優(yōu)化洼畅,它將業(yè)務(wù)邏輯和業(yè)務(wù)展示
也做了一層隔離, 對應(yīng)的就變成了MVCP吩案。
??M和V功能不變,原來的C現(xiàn)在只負(fù)責(zé)布局帝簇,而所有的業(yè)務(wù)邏輯全都轉(zhuǎn)移到了P層徘郭。
??P層處理完了業(yè)務(wù)邏輯,如果要更改view的顯示丧肴,那么可以通過回調(diào)來實(shí)現(xiàn)残揉,這樣可以減輕耦合,同時可以單獨(dú)測試P層的業(yè)務(wù)邏輯芋浮。??在 MVP 中抱环,P可以理解為松散的控制器,其中包含了視圖的 UI 業(yè)務(wù)邏輯纸巷,所有從視圖發(fā)出的事件镇草,都會通過代理方法Protocol給 P 進(jìn)行處理;同時瘤旨,P也通過視圖暴露的接口與其進(jìn)行通信梯啤。
- View負(fù)責(zé)界面展示和布局管理,向Presenter暴露視圖更新和數(shù)據(jù)獲取的接口
- Presenter負(fù)責(zé)接收來自View的事件存哲,通過View提供的接口更新視圖,并管理Model
- Model和MVC中的一樣,提供數(shù)據(jù)模型
這個流程看起來確實(shí)很像 Apple 的理想化的MVC蒋譬,它的名字是 MVP(被動變化的 View)找岖。
Apple 的 MVC 實(shí)際上是 MVP 嗎?不是的
區(qū)別就是IOS中:
(1)蘋果的理想MVC中UIView相當(dāng)于View,UIController是Controller,而在MVP中,UIView和UIController都相當(dāng)于View户盯,所以在 Presenter 里面基本沒什么布局相關(guān)的代碼,它的職責(zé)只是通過數(shù)據(jù)和狀態(tài)更新 View魂爪。
(2)持有關(guān)系也不一樣先舷,MVC中 C 持有 M和V,但是在MVP中 V 持有 P滓侍,P 持有M 蒋川。
??MVP相對于MVC,它其實(shí)只做了一件事情撩笆,即分割業(yè)務(wù)展示和業(yè)務(wù)邏輯. 展示和邏輯分開后捺球,只要我們能保證V在收到P的數(shù)據(jù)更新通知后能正常刷新頁面,那么整個業(yè)務(wù)就沒有問題夕冲。因為V收到的通知其實(shí)都是來自于P層的數(shù)據(jù)獲取/更新操作, 所以我們只要保證P層的這些操作都是正常的就可以了氮兵。 即我們只用測試P層的邏輯,不必關(guān)心V層的情況歹鱼。
??所以MVP實(shí)現(xiàn)了各模塊的解藕泣栈,具有更好的可測試性。但是總體代碼量比MVC大弥姻。
三南片、MVVM
??MVVM其實(shí)是在MVP的基礎(chǔ)上發(fā)展起來的。那么MVVM在MVP的基礎(chǔ)上改良了啥呢庭敦?答案就是數(shù)據(jù)綁定疼进。
??MVVM各層的職責(zé)和MVP的類似,viewModel對應(yīng)P層秧廉,只是在MVVM的View層多了數(shù)據(jù)綁定的操作伞广。
- 在MVVM 中,View和Controller正式聯(lián)系在一起疼电,我們把它們視為一個組件
- View和Controller 都不能直接引用model嚼锄,而是引用視圖模型(viewModel)
- viewModel 是一個放置用戶輸入驗證邏輯,視圖顯示邏輯蔽豺,發(fā)起網(wǎng)絡(luò)請求和其他代碼的地方
- 使用MVVM會輕微的增加代碼量区丑,但總體上減少了代碼的復(fù)雜性。
MVVM 的使用建議
- MVVM 配合一個綁定機(jī)制效果最好(ReactiveCocoa茫虽,KVO)刊苍。
- Controller 盡量不涉及業(yè)務(wù)邏輯,讓 viewModel 去做這些事情濒析。
- Controller 只是一個中間人正什,接收 view 的事件、調(diào)用 viewModel 的方法号杏、響應(yīng) viewModel 的變化婴氮。
- viewModel 絕對不能包含視圖 view(UIKit.h),不然就跟 view 產(chǎn)生了耦合盾致,不方便復(fù)用和測試主经。
- viewModel之間可以有依賴。
- viewModel避免過于臃腫庭惜,否則重蹈Controller的覆轍罩驻,變得難以維護(hù)。
MVVM優(yōu)點(diǎn)
- MVVM 可以兼容你當(dāng)下使用的MVC架構(gòu)护赊。
- MVVM 增加你的應(yīng)用的可測試性惠遏。
- 低耦合:View 可以獨(dú)立于Model變化和修改,一個 viewModel 可以綁定到不同的 View 上
- 可重用性:可以把一些視圖邏輯放在一個 viewModel里面骏啰,讓很多 view 重用這段視圖邏輯
- 獨(dú)立開發(fā):開發(fā)人員可以專注于業(yè)務(wù)邏輯和數(shù)據(jù)的開發(fā) viewModel节吮,設(shè)計人員可以專注于頁面設(shè)計
- 可測試:通常界面是比較難于測試的,而 MVVM 模式可以針對 viewModel來進(jìn)行測試
缺點(diǎn)
- 學(xué)習(xí)成本和開發(fā)成本都很高,新人很難上手
- iOS中判耕,并沒有現(xiàn)成的綁定機(jī)制可用透绩,要么使用 KVO,要么引入類似 ReactiveCocoa 這樣的第三方庫
- 數(shù)據(jù)綁定使 Debug 變得更難了壁熄,堆棧結(jié)構(gòu)更復(fù)雜了帚豪,使得對象生命周期很難追蹤
- 對于過大的項目,數(shù)據(jù)綁定需要花費(fèi)更多的內(nèi)存
- ReactiveCocoa 在國內(nèi)外還都是在小眾領(lǐng)域请毛,沒有被大量接受成為主流的編程框架志鞍。在別的語言中,例如 Java 中的 RxJava 也同樣沒有成為主流