《論MVVM偽框架結(jié)構(gòu)和MVC中M的實(shí)現(xiàn)機(jī)制及M層的構(gòu)建》閱讀筆記
原文鏈接
* 業(yè)務(wù)類中的屬性設(shè)計(jì)為只讀。
* 數(shù)據(jù)模型類中的屬性定義最好也設(shè)置為只讀,因?yàn)閿?shù)據(jù)模型的建立是在業(yè)務(wù)類方法內(nèi)部完成并通過通知或者異步回調(diào)的方式交給使用者踊兜。而不應(yīng)該交由使用者來創(chuàng)建和更新锚沸。
* 數(shù)據(jù)模型類一般提供一個(gè)帶有所有屬性的init初始化方法横腿,而初始化后這些屬性原則上是不能被再次改變,所以應(yīng)該設(shè)置為只讀屬性棕叫。
- 優(yōu)秀的框架中各層次的拆分并不是簡(jiǎn)單的將代碼進(jìn)行歸類和劃分,層次的劃分是橫向的奕删,而模塊的劃分是縱向的俺泣。
- 視圖負(fù)責(zé)展示和渲染,模型負(fù)責(zé)業(yè)務(wù)邏輯的實(shí)現(xiàn)完残,控制負(fù)責(zé)調(diào)度視圖的事件以及業(yè)務(wù)邏輯的調(diào)用以及通知視圖的刷新通知伏钠。
- 不能將M層簡(jiǎn)單理解為干巴巴的只有屬性沒有方法的數(shù)據(jù)模型。
- M層是業(yè)務(wù)模型層而非數(shù)據(jù)模型層谨设。
- 優(yōu)秀的應(yīng)用和框架并不在代碼的多寡熟掂,而是整體系統(tǒng)的代碼簡(jiǎn)單易讀,各部分職責(zé)分明扎拣,容易維護(hù)和調(diào)試赴肚。
- M層要完成對(duì)業(yè)務(wù)邏輯實(shí)現(xiàn)的封裝,一般業(yè)務(wù)邏輯最多的是涉及到客戶端和服務(wù)器之間的業(yè)務(wù)交互鹏秋。M層要完成對(duì)應(yīng)用網(wǎng)絡(luò)協(xié)議和服務(wù)器之間的交互數(shù)據(jù)格式尊蚁,本地緩存和數(shù)據(jù)庫(kù)存儲(chǔ)等所有業(yè)務(wù)細(xì)節(jié)的封裝,這些東西不能暴露給C層侣夷,只給其提供一個(gè)接口横朋。
- C層的作用就是處理視圖的事件,然后調(diào)用業(yè)務(wù)邏輯百拓,接收業(yè)務(wù)邏輯的處理結(jié)果通知琴锭,然后通知視圖去刷新界面。
- M層是生產(chǎn)者衙传,負(fù)責(zé)數(shù)據(jù)的構(gòu)建和更新决帖,C和V層負(fù)責(zé)數(shù)據(jù)的使用和消費(fèi)。
- C具有負(fù)責(zé)創(chuàng)建并持有M層對(duì)象的責(zé)任蓖捶,C層也是一個(gè)使用觀察者地回。
- C層負(fù)責(zé)M層的方法調(diào)用。
- C層負(fù)責(zé)觀察M層的數(shù)據(jù)變化通知并進(jìn)行相應(yīng)處理。
M應(yīng)該做的事:
給ViewController提供數(shù)據(jù)
給ViewController存儲(chǔ)數(shù)據(jù)提供接口
提供經(jīng)過抽象的業(yè)務(wù)基本組件刻像,供Controller調(diào)度
C應(yīng)該做的事:
管理View Container的生命周期
負(fù)責(zé)生成所有的View實(shí)例畅买,并放入View Container
監(jiān)聽來自View與業(yè)務(wù)有關(guān)的事件,通過與Model的合作细睡,來完成對(duì)應(yīng)事件的業(yè)務(wù)谷羞。
V應(yīng)該做的事:
響應(yīng)與業(yè)務(wù)無關(guān)的事件,并因此引發(fā)動(dòng)畫效果溜徙,點(diǎn)擊反饋(如果合適的話湃缎,盡量還是放在View去做)等。
界面元素表達(dá)
delegate這種模式并不局限于M和C之間蠢壹,同樣也可以應(yīng)用在V和C之間嗓违。
delegate本質(zhì)其實(shí)是一種雙方之間通信的接口,而通過接口來進(jìn)行通信則可以最大限度的減少對(duì)象之間的耦合图贸。
除了delegate外也可以采用Block異步通知方式
typedef void (^BlockHandler)(id obj, NSError *error);
采用block方式定義異步方法時(shí)一般要符合如下幾個(gè)規(guī)則:
-
BlockHandler
的參數(shù)確保就是固定的2個(gè):一個(gè)是異步方法返回的對(duì)象靠瞎,這個(gè)對(duì)象可以根據(jù)不同的方法而返回不同的對(duì)象。一個(gè)NSError
對(duì)象表示異步訪問發(fā)生了錯(cuò)誤的返回求妹。 - 將
block回調(diào)
處理作為方法的最后一個(gè)參數(shù)乏盐。 - 不建議在一個(gè)方法中出現(xiàn)兩個(gè)block回調(diào):一個(gè)正確的和一個(gè)失敗的。
- 推薦:對(duì)于在M層對(duì)象中 某個(gè)請(qǐng)求通過
block
回調(diào)來通知調(diào)用者進(jìn)行異步更新的機(jī)制制恍。一個(gè)原則父能,只要涉及到M層對(duì)象的方法調(diào)用都盡可能走標(biāo)準(zhǔn)block
回調(diào)這種方式。例如:
- (void)fn1:(參數(shù)類型)參數(shù) callback:(BlockHandler)callback;
- (void)fn2:(參數(shù)類型)參數(shù) callback:(BlockHandler)callback;
- (void)fn4:(參數(shù)類型)參數(shù) callback:(BlockHandler)callback;
- (void)fn5:(參數(shù)類型)參數(shù) callback:(BlockHandler)callback;
上面的方法實(shí)現(xiàn)和調(diào)用機(jī)制看起來都很統(tǒng)一而且是標(biāo)準(zhǔn)化净神。即使某個(gè)方法并沒有任何異步動(dòng)作何吝,也最好遵守這種模式,因?yàn)槟程煊锌赡軙?huì)從同步實(shí)現(xiàn)變?yōu)楫惒綄?shí)現(xiàn)鹃唯。這樣的話只需改動(dòng)C層的代碼即可爱榕。
delegate異步通知和Block異步通知的選擇參考:
- 如果某個(gè)類中具有很多個(gè)方法,而每個(gè)方法又實(shí)現(xiàn)了不同的功能坡慌,并且方法的異步返回?cái)?shù)據(jù)和這個(gè)方法具有很強(qiáng)的關(guān)聯(lián)性就應(yīng)該考慮使用
block
而不是delegate
黔酥。 - 如果類中的方法的異步方法是那種一次交互就得到一個(gè)不同的結(jié)果,而且得到的結(jié)果和上次結(jié)果沒什么關(guān)聯(lián)洪橘,就考慮使用
block
而不是delegate
跪者。 - 如果我們調(diào)用類中的某個(gè)方法,而調(diào)用前設(shè)置了一些上下文熄求,而調(diào)用方法后我們又希望根據(jù)這個(gè)上下文來處理的返回結(jié)果時(shí)渣玲,就考慮使用
block
而不是delegate
。 - 如果我們調(diào)用類里面的某個(gè)方法弟晚,而返回的結(jié)果不需要和上下文進(jìn)行關(guān)聯(lián)那么就考慮使用
Delegate
而不用block
忘衍。 - 如果要實(shí)時(shí)的觀察業(yè)務(wù)類里面的某個(gè)屬性的變化時(shí)逾苫,我們就應(yīng)該考慮使用
Delegate
而不是使用block
。 - 如果業(yè)務(wù)類里面的異步通知可能分為好幾個(gè)步驟那么就考慮使用
Delegate
而不是使用block
枚钓。
什么場(chǎng)景下用KVO的方式實(shí)現(xiàn)異步通知回調(diào):
- 某個(gè)對(duì)象的同一數(shù)據(jù)更新可能會(huì)引起多個(gè)依賴這個(gè)對(duì)象的對(duì)象的更新變化處理隶垮。
- 如果某個(gè)對(duì)象的生命周期要比觀察者短則不建議用KVO的方式,因?yàn)檫@個(gè)有可能會(huì)導(dǎo)致系統(tǒng)的崩潰而造成巨大的影響秘噪。
delegate和block的缺點(diǎn)
-
delegate
的方式必須要事先定義出一個(gè)接口協(xié)議來,并且調(diào)用者和實(shí)現(xiàn)者都需要按照這個(gè)接口規(guī)則來進(jìn)行通知和數(shù)據(jù)處理交互勉耀,這樣無形中就產(chǎn)生了一定的耦合性指煎,也就是二者之間還是具有隱式的依賴。不利于擴(kuò)展和進(jìn)行完全自定義處理便斥。 -
block
的缺點(diǎn):- 是使用不好會(huì)產(chǎn)生循環(huán)引用的問題
- 出錯(cuò)后難以調(diào)試以及難以進(jìn)行問題追蹤
- 代碼中產(chǎn)生多重嵌套至壤,從而影響代碼的美觀和可讀性
KVO機(jī)制的優(yōu)點(diǎn)
業(yè)務(wù)對(duì)象和觀察者之間完全脫離了耦合性,而且數(shù)據(jù)變化后的通知完全由系統(tǒng)來處理枢纠,不需要添加附加的代碼和邏輯像街,而且可以實(shí)現(xiàn)多觀察者同時(shí)監(jiān)聽一份數(shù)據(jù)。
缺點(diǎn):只能對(duì)屬性的變化進(jìn)行觀察晋渺。
NSNotification缺點(diǎn)
這種機(jī)制過于松散镰绎,沒有關(guān)聯(lián)的上下文。給使用者帶來了一定的學(xué)習(xí)成本木西。
總結(jié)
在設(shè)計(jì)一個(gè)業(yè)務(wù)層時(shí)畴栖,首先應(yīng)該要對(duì)業(yè)務(wù)進(jìn)行仔細(xì)的分析和理解,然后構(gòu)建出一個(gè)類結(jié)構(gòu)圖八千,這種靜態(tài)框架設(shè)計(jì)好之后吗讶,就需要對(duì)類進(jìn)行角色和職責(zé)劃分,哪些應(yīng)該設(shè)計(jì)為數(shù)據(jù)模型類恋捆,哪些應(yīng)該設(shè)計(jì)為業(yè)務(wù)類照皆。