前言
最近讀到羅琦的架構(gòu)分享:VIP模式,感覺是個"性價比"非常高的架構(gòu)模式.在此記錄一些學(xué)習(xí)和思考.
當(dāng)前模式
MVC的詬病很清晰,所以都在尋找更好的模式.后來的MVP,并沒有解決MVC的問題.然后MVVM,乃至更多的模式.我個人覺得似乎都或多或少有一些缺陷.而我目前沿用單項MVVM+P的模式,在VIP模式下,似乎通暢了不少.
MVC作為蘋果推薦模式,controller代碼爆炸,無法測試等詬病很清晰.
MVP把controller作為presenter,并沒有實際改善MVC中C的問題.
MVVM很熱,有RAC支持,能夠非常好的解決問題,但是我不喜歡.
其余的模式,例如視頻中提到的viper模式,不太常見,理解不深.借用視頻中的話:Over Design
MVVM
MVVM = Model + View + ViewModel
Model為數(shù)據(jù)存儲,也就是各種property
View為顯示,各種UIView和其subclass的組合
ViewModel為粘合劑.我所理解的為:就是以前的business.
我不喜歡的原因是,MVVM還具備一個特性:雙向性.也就是說View的變化,會反映在ViewMode上;ViewModel變化,也會導(dǎo)致View變化.
為了實現(xiàn)這個特性,一般依賴RAC(KVO).
我不成熟的理解:設(shè)計模式是對工作(代碼)的拆分與組合,以達(dá)到"高內(nèi)聚,低耦合"的目的,而并不希望它依賴某個東西.因為學(xué)習(xí)并且維護(hù)某個依賴項是有成本的.
RAC的優(yōu)勢極度明顯,雖也有一定的劣勢:
- 學(xué)習(xí)曲線(其實這不算是問題,通過學(xué)習(xí)解決)
- 大量的KVO,效率問題(無法解決,但是效率瓶頸一般不在這里)
- 調(diào)用棧長(通過經(jīng)驗解決)
但是這并不是最主要的原因.最主要的原因是RAC是改變的一個編程思想:響應(yīng)式.包括信號,觀察,訂閱等.如果要使用RAC,那么是否整個工程都要改變思想呢?
朋友所在的某擁有2億+用戶的知名創(chuàng)業(yè)公司,曾經(jīng)為了引入RAC,花了一個多月的時間將工程整體改造.
VIP
看到這個模式,感覺把我自己采用的模式進(jìn)行了一個非常不錯的升級.通過對項目的初步實驗和改造,以下為我的學(xué)習(xí)和理解.
VIP = View + Interactor + Presenter
換個說法可以理解為依賴Protocol的,單向的ViewController + Model + View + Fetcher(Interactor) + Transformer(Presenter)
主要依賴2個Protocol(視頻中是3個):
1.FetcherOutput
2.TransformerOutput
意思是,當(dāng)fetcher去獲取(fetch)數(shù)據(jù)完成后,通過FetcherOutput進(jìn)行數(shù)據(jù)輸出;同理,當(dāng)Transformer進(jìn)行數(shù)據(jù)轉(zhuǎn)換(transform)后,也通過代理進(jìn)行數(shù)據(jù)輸出.
總體來看,因為是單向的,所以不存在雙向數(shù)據(jù)綁定的問題.由ViewController在合適的時機(jī)(生命周期/點(diǎn)擊按鈕等),通過fetcher調(diào)用數(shù)據(jù).調(diào)用成功后,此時的數(shù)據(jù)為原始數(shù)據(jù).將原始數(shù)據(jù)交付給delegate,既:transformer.通過transformer進(jìn)行數(shù)據(jù)運(yùn)算和轉(zhuǎn)換(dict/model)后,交給delegate進(jìn)行displayer.當(dāng)然這里的delegate即為ViewController本身.
偽代碼:
在ViewController中:
- (void)viewDidLoad {
[self setupVIP];
[self.datafetcher fetchData];
}
- (void)setupVIP {
self.fetcher = [Fetcher new];
self.transformer = [Transformer new];
//設(shè)置fetcher的output代理
self.fetcher.output = self.transformer;
//設(shè)置transformer的output代理
self.transformer.output = self;
}
//transformer的代理方法:display
- (void)displayData:(id)data {
//display by tableview,etc...
}
在Fetcher中:
- (void)fetchData {
/*
在視頻中專門為獲取數(shù)據(jù)封裝了一個worker類,目的是可以方便的切換數(shù)據(jù)來源.
沒有需求的話或許也可以簡化.
*/
xxxx (fetch data from api/db)
[self.dataformatter tranformData:data];
}
在Transformer中:
- (void)tranformData:(id)data {
xxxx(transform data)
[self.displayer displayData:data]
}
感受
設(shè)計模式最終是為了更好的維護(hù)項目.從實際出發(fā)我覺得最好能達(dá)到幾個效果.
- 團(tuán)隊基本能寫出風(fēng)格一致的代碼,容易修改/維護(hù)
- 新人能夠迅速的理解并且加入
- 接手的人能夠快速的接手并且修改/維護(hù)
- 能夠更加容易的進(jìn)行測試
我稱之為"性價比",VIP模式我個人認(rèn)為"性價比"還蠻高的.我會繼續(xù)學(xué)習(xí)和使用,也推薦大家測試一番.