1、MVC的理想模型
從字面意思來(lái)理解郭毕,MVC 即 Model View Controller(模型 視圖 控制器),是 Xerox PARC 在 20 世紀(jì) 80 年代為編程語(yǔ)言 Smalltalk-80 發(fā)明的一種軟件設(shè)計(jì)模式,至今已廣泛應(yīng)用于用戶交互應(yīng)用程序中许蓖。其用意在于將數(shù)據(jù)與視圖分離開(kāi)來(lái)窖杀。在 iOS 開(kāi)發(fā)中 MVC 的機(jī)制被使用的淋漓盡致漓摩,充分理解 iOS 的 MVC 模式,有助于我們程序的組織合理性入客。
MVC 的幾個(gè)明顯的特征和體現(xiàn):
1管毙、View 上面顯示什么東西,取決于 Model桌硫。
2夭咬、只要 Model 數(shù)據(jù)改了,View 的顯示狀態(tài)會(huì)跟著更改铆隘。
- Models:?數(shù)據(jù)層卓舵,負(fù)責(zé)數(shù)據(jù)的處理和獲取的數(shù)據(jù)接口層。
- Views: 展示層(GUI)膀钠,對(duì)于 iOS 來(lái)說(shuō)所有以 UI 開(kāi)頭的類(lèi)基本都屬于這層掏湾。
- Controller:控制器層,它是 Model 和 View 之間的膠水或者說(shuō)是中間人肿嘲。一般來(lái)說(shuō)融击,當(dāng)用戶對(duì) View 有操作時(shí)它負(fù)責(zé)去修改相應(yīng) Model;當(dāng) Model 的值發(fā)生變化時(shí)它負(fù)責(zé)去更新對(duì)應(yīng) View雳窟。
如上圖所示尊浪,M和View應(yīng)該是完全隔離的,由C作為中間人來(lái)負(fù)責(zé)二者的交互封救,同時(shí)三者是完全獨(dú)立分開(kāi)的拇涤,這樣可以保證M和V的可測(cè)試性和復(fù)用性,但是一般由于C都是為特別的應(yīng)用場(chǎng)景下的M和V做中介者兴泥,所以很難復(fù)用工育。
2、MVC在iOS里面的實(shí)現(xiàn)
實(shí)際上在iOS里面MVC的實(shí)現(xiàn)方式很難做到如上所述的那樣搓彻,因?yàn)橛捎贏pple的規(guī)范如绸,一個(gè)界面的呈現(xiàn)都需要構(gòu)建一個(gè)viewcontroller嘱朽,而每個(gè)viewcontroller都帶有一個(gè)根view,這就導(dǎo)致C和V緊密耦合在一起構(gòu)成了iOS里面的C層怔接。
apple里面的MVC真正寫(xiě)起來(lái)大概如下圖所示:
3搪泳、iOS的MVC各層職責(zé)
controller層(VC):
1、生成view扼脐,然后組裝view
2岸军、響應(yīng)View的事件和作為view的代理
3、調(diào)用model的數(shù)據(jù)獲取接口瓦侮,拿到返回?cái)?shù)據(jù)艰赞,處理加工,渲染到view顯示
4肚吏、處理view的生命周期
5方妖、處理界面之間的跳轉(zhuǎn)
model層:
1、業(yè)務(wù)邏輯封裝
2罚攀、提供數(shù)據(jù)接口給controller使用
3党觅、數(shù)據(jù)持久化存儲(chǔ)和讀取
4、作為數(shù)據(jù)模型存儲(chǔ)數(shù)據(jù)
view層:
1斋泄、界面元素搭建杯瞻,動(dòng)畫(huà)效果,數(shù)據(jù)展示炫掐,
2魁莉、接受用戶操作并反饋視覺(jué)效果
4、MVC中M層實(shí)現(xiàn)的準(zhǔn)則
-
定義的M層中的代碼應(yīng)該和V層和C層完全無(wú)關(guān)的卒废,也就是M層的對(duì)象是不需要依賴(lài)任何C層和V層的對(duì)象而獨(dú)立存在的沛厨。整個(gè)框架的設(shè)計(jì)最優(yōu)結(jié)構(gòu)是V層不依賴(lài)C層而獨(dú)立存在宙地,M層不依賴(lài)C層和V層獨(dú)立存在摔认,C層負(fù)責(zé)關(guān)聯(lián)二者,V層只負(fù)責(zé)展示宅粥,M層持有數(shù)據(jù)和業(yè)務(wù)的具體實(shí)現(xiàn)参袱,而C層則處理事件響應(yīng)以及業(yè)務(wù)的調(diào)用以及通知界面更新。三者之間一定要明確的定義為單向依賴(lài)秽梅,而不應(yīng)該出現(xiàn)雙向依賴(lài)抹蚀。下面是三層的依賴(lài)關(guān)系圖:
-
M層要完成對(duì)業(yè)務(wù)邏輯實(shí)現(xiàn)的封裝,一般業(yè)務(wù)邏輯最多的是涉及到客戶端和服務(wù)器之間的業(yè)務(wù)交互企垦。M層里面要完成對(duì)使用的網(wǎng)絡(luò)協(xié)議(HTTP, TCP环壤,其他)、和服務(wù)器之間交互的數(shù)據(jù)格式(XML, JSON,其他)钞诡、本地緩存和數(shù)據(jù)庫(kù)存儲(chǔ)(COREDATA, SQLITE,其他)等所有業(yè)務(wù)細(xì)節(jié)的封裝郑现,而且這些東西都不能暴露給C層湃崩。所有供C層調(diào)用的都是M層里面一個(gè)個(gè)業(yè)務(wù)類(lèi)所提供的成員方法來(lái)實(shí)現(xiàn)。也就是說(shuō)C層是不需要知道也不應(yīng)該知道和客戶端和服務(wù)器通信所使用的任何協(xié)議接箫,以及數(shù)據(jù)報(bào)文格式攒读,以及存儲(chǔ)方面的內(nèi)容。這樣的好處是客戶端和服務(wù)器之間的通信協(xié)議辛友,數(shù)據(jù)格式薄扁,以及本地存儲(chǔ)的變更都不會(huì)影響任何的應(yīng)用整體框架,因?yàn)樘峁┙oC層的接口不變废累,只需要升級(jí)和更新M層的代碼就可以了邓梅。比如說(shuō)我們想將網(wǎng)絡(luò)請(qǐng)求庫(kù)從ASI換成AFN就只要在M層變化就可以了,整個(gè)C層和V層的代碼不變邑滨。下面是M層內(nèi)部層次的定義圖:
M層如何和C層交互的問(wèn)題也需要考慮震放,因?yàn)镸層是不需要知道C層和V層的存在的,那么M層在業(yè)務(wù)處理完畢后如何去通知C層呢驼修?方法有很多種:
1殿遂、我們可以為M層的通知邏輯定義Delegate協(xié)議,然后讓C層去實(shí)現(xiàn)這些協(xié)議乙各,然后M層提供一個(gè)delegate屬性來(lái)賦值處理業(yè)務(wù)通知的對(duì)象墨礁。
2、我們也可以定義眾多的NSNotification或者事件總線耳峦,然后當(dāng)M層的業(yè)務(wù)處理完畢后可以發(fā)送通知恩静,并且在C層實(shí)現(xiàn)通知的處理邏輯。
3蹲坷、我們可以用閉包回調(diào)或者接口匿名實(shí)現(xiàn)對(duì)象的形式來(lái)實(shí)現(xiàn)業(yè)務(wù)邏輯完成的通知功能驶乾。
總結(jié)來(lái)說(shuō):
M層不應(yīng)該是數(shù)據(jù)模型,放幾個(gè)屬性就完事了循签。而應(yīng)該是承載業(yè)務(wù)邏輯和數(shù)據(jù)存儲(chǔ)獲取的職責(zé)一層级乐。
5、MVC優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1县匠、代碼復(fù)用: 三個(gè)小模塊的V(cell/userInfoView)對(duì)外只暴露Set方法, 對(duì)M甚至C都是隔離狀態(tài), 復(fù)用完全沒(méi)有問(wèn)題. 三個(gè)大模塊的MVC也可以用于快速構(gòu)建相似的業(yè)務(wù)場(chǎng)景(大模塊的復(fù)用比小模塊會(huì)差一些, 下文我會(huì)說(shuō)明).
2风科、易拓展性: 當(dāng)模型,數(shù)據(jù)與控制器是相分離的時(shí)候乞旦,改變業(yè)務(wù)規(guī)則就變得很容易贼穆,數(shù)據(jù)的存儲(chǔ)可以隨意的遷移,因?yàn)槟P蛯?duì)控制器的接口是不變的兰粉,這樣界面仍然可以正確的展示故痊,界面UI也是可以任意改變,因?yàn)樗魂P(guān)心界面不會(huì)影響到其他.
3玖姑、可維護(hù)性: 各個(gè)模塊間職責(zé)分離, 哪里出錯(cuò)改哪里, 完全不影響其他模塊. 利于多人團(tuán)隊(duì)開(kāi)發(fā)
缺點(diǎn):
1愕秫、沒(méi)有區(qū)分業(yè)務(wù)邏輯和業(yè)務(wù)展示, 這對(duì)單元測(cè)試很不友好.
2浊仆、增加了系統(tǒng)結(jié)構(gòu)和實(shí)現(xiàn)的復(fù)雜性。對(duì)于簡(jiǎn)單的界面豫领,嚴(yán)格遵循MVC抡柿,使模型、視圖與控制器分離等恐,會(huì)增加結(jié)構(gòu)的復(fù)雜性洲劣,并可能產(chǎn)生過(guò)多的更新操作,降低運(yùn)行效率课蔬。
3囱稽、視圖對(duì)模型數(shù)據(jù)的低效率訪問(wèn)。依據(jù)模型操作接口的不同二跋,視圖可能需要多次調(diào)用才能獲得足夠的顯示數(shù)據(jù)战惊。對(duì)未變化數(shù)據(jù)的不必要的頻繁訪問(wèn),也將損害操作性能扎即。
4吞获、業(yè)務(wù)邏輯和業(yè)務(wù)展示強(qiáng)耦合: 可以看到, 有些業(yè)務(wù)邏輯(頁(yè)面跳轉(zhuǎn)/點(diǎn)贊/分享…)是直接散落在V層的, 這意味著我們?cè)跍y(cè)試這些邏輯時(shí), 必須首先生成對(duì)應(yīng)的V, 然后才能進(jìn)行測(cè)試. 顯然, 這是不合理的. 因?yàn)闃I(yè)務(wù)邏輯最終改變的是數(shù)據(jù)M, 我們的關(guān)注點(diǎn)應(yīng)該在M上, 而不是展示M的V.
參考博客
iOS MVC、MVVM谚鄙、MVP詳解 - 簡(jiǎn)書(shū) (jianshu.com)
深入分析MVC各拷、MVP、MVVM闷营、VIPER (juejin.cn)
iOS中MVC設(shè)計(jì)模式的優(yōu)缺點(diǎn)_dxm_8888的博客-CSDN博客_ios mvc優(yōu)點(diǎn)