MVVM奇葩說(shuō)

轉(zhuǎn)載請(qǐng)注明出處:http://www.olinone.com/

一直想聊聊這個(gè)話題,也有朋友跟我留言锌唾,讓我講講MVVM,只可惜一直沒(méi)整明白,不敢輕易下筆晌涕。針對(duì)MVVM滋捶,網(wǎng)上有很多不錯(cuò)的文章,比如MVVM介紹余黎、被誤解的 MVC 和被神化的 MVVM以及Look at MVVM from a different perspective等等

文章前我想先提幾個(gè)問(wèn)題

1重窟、MVVM到底是什么?它和MVC有什么區(qū)別惧财?

2亲族、MVVM中VM到底是個(gè)什么角色?它和Controller或者M(jìn)anager有什么區(qū)別可缚?

3霎迫、ViewController在MVVM中扮演怎樣角色?Api數(shù)據(jù)請(qǐng)求放在哪里帘靡?數(shù)據(jù)流向如何知给?

MVVM簡(jiǎn)介

關(guān)于MVVM,相信大家或多或少都有了解描姚。引用MVVM介紹文中一圖

受MVC或MVP架構(gòu)的影響涩赢,對(duì)MVVM最初印象以為這是一個(gè)以ViewModel為核心,處理View和Model的開(kāi)發(fā)架構(gòu)轩勘。于是乎在原有MVC的基礎(chǔ)上筒扒,創(chuàng)建了一個(gè)所謂的ViewModel對(duì)象,然后把ViewController中的代碼移到ViewModel中绊寻,在ViewModel里面處理View以及Model的所有邏輯花墩。畢竟大家都在說(shuō)MVVM可以為ViewController瘦身,這ViewController就剩創(chuàng)建ViewModel的代碼澄步,嗯冰蘑,夠瘦身,這就是MVVM村缸!

慢慢的祠肥,發(fā)現(xiàn)有什么地方不對(duì),哪里不對(duì)梯皿?第一想法就是ViewController的定位仇箱,View?不是东羹,Controller剂桥?也不是!畢竟它就創(chuàng)建ViewModel百姓,好像與View渊额、Model也沒(méi)啥關(guān)系。拋開(kāi)ViewController不談垒拢,突然發(fā)現(xiàn)這樣的ViewModel旬迹、Model以及View不就是MVC,一個(gè)以ViewModel為中心的MVC求类!

錯(cuò)在哪里

核心問(wèn)題就在于對(duì)ViewModel角色的定位不清奔垦!基于MVVM設(shè)計(jì)思路,ViewModel存在目的在于抽離ViewController中展示業(yè)務(wù)邏輯尸疆,而不是替代ViewController椿猎,其它視圖操作業(yè)務(wù)等還是應(yīng)該放在ViewController中實(shí)現(xiàn)

既然不負(fù)責(zé)視圖操作邏輯,ViewModel中就不應(yīng)該存在任何View對(duì)象寿弱,更不應(yīng)該存在Push/Present等視圖跳轉(zhuǎn)邏輯犯眠。因此,ViewModel中絕不應(yīng)該存在任何視圖操作相關(guān)的代碼

@interface ViewModel : NSObject

// viewmodel中切不可存在view對(duì)象症革,更不該出現(xiàn)push或者present代碼

- (instancetype)initWithTableView:(UITableView *)tableView;

@end

ViewModel做啥

很簡(jiǎn)單筐咧,處理視圖展示邏輯,ViewModel負(fù)責(zé)將數(shù)據(jù)業(yè)務(wù)層提供的數(shù)據(jù)轉(zhuǎn)化為界面展示所需的VO噪矛。其與View一一對(duì)應(yīng)量蕊,沒(méi)有View就沒(méi)有ViewModel

比如,數(shù)據(jù)業(yè)務(wù)層傳遞一個(gè)含有性別屬性sex的DO對(duì)象艇挨,0表示男残炮, 1表示女。ViewModel的職責(zé)就是將其轉(zhuǎn)化為展示層可顯示的VO對(duì)象

self.personVO.sex = personDO.sex == 0 ? @"男": @"女";

ViewModel和View一起組成DDD(Model-Driven Design)領(lǐng)域驅(qū)動(dòng)架構(gòu)體系中的Presentation展示層缩滨。在iOS中势就,數(shù)據(jù)流向可以表示為ViewModel->ViewController->View,ViewController負(fù)責(zé)連接VO及其對(duì)應(yīng)的View對(duì)象

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)對(duì)于安卓童鞋可能非常熟悉脉漏,有興趣的童鞋可以參考這篇文章蛋勺,本文不做過(guò)多講解,借用其描述介紹幾個(gè)名詞

1鸠删、VO(View Object):視圖對(duì)象抱完,用于展示層,它的作用是把某個(gè)指定頁(yè)面(或組件)的所有數(shù)據(jù)封裝起來(lái)

2刃泡、DO(Domain Object):領(lǐng)域?qū)ο笄捎椋褪菑默F(xiàn)實(shí)世界中抽象出來(lái)的有形或無(wú)形的業(yè)務(wù)實(shí)體

3、PO(Persistent Object):持久化對(duì)象烘贴,它跟持久層(通常是關(guān)系型數(shù)據(jù)庫(kù))的數(shù)據(jù)結(jié)構(gòu)形成一一對(duì)應(yīng)的映射關(guān)系禁添,如果持久層是關(guān)系型數(shù)據(jù)庫(kù),那么桨踪,數(shù)據(jù)表中的每個(gè)字段(或若干個(gè))就對(duì)應(yīng)PO的一個(gè)(或若干個(gè))屬性

4老翘、Domain:領(lǐng)域驅(qū)動(dòng)層,是用戶與數(shù)據(jù)庫(kù)交互的核心中轉(zhuǎn)站,控制用戶數(shù)據(jù)收集铺峭,控制請(qǐng)求轉(zhuǎn)向等

MVVM架構(gòu)中墓怀,ViewModel連接視圖View和數(shù)據(jù)業(yè)務(wù)Model層,而Domain和Data數(shù)據(jù)持久層共同組成整個(gè)Model層卫键。完整結(jié)構(gòu)如圖所示

Model并不表示Model

MVVM架構(gòu)中的M傀履,并不表示Model對(duì)象,而是表示整個(gè)數(shù)據(jù)業(yè)務(wù)層莉炉,對(duì)應(yīng)DDD架構(gòu)中的Domain層以及數(shù)據(jù)Data層钓账。業(yè)務(wù)開(kāi)發(fā)中,一般考慮Api或者DB對(duì)象絮宁,極少考慮Domain層設(shè)計(jì)梆暮,也不會(huì)區(qū)分DO或者PO對(duì)象∩馨海籠統(tǒng)定義Model 啦粹,將其傳遞給展示層ViewModel,久而久之治专,Model對(duì)象承載的信息越來(lái)越多卖陵,更有甚者,在Model中處理業(yè)務(wù)邏輯张峰,導(dǎo)致項(xiàng)目維護(hù)成本增加泪蔫,代碼中出現(xiàn)if..else的概率也會(huì)越來(lái)越大

@interface PersonModel : NSObject

@property (nonatomic, assign) NSInteger sex;

@property (nonatomic, readonly) NSString *sexDescription;

@end

@implementation PersonModel

// model中不應(yīng)該存在業(yè)務(wù)邏輯代碼

- (NSString *)sexDescription {

? ? return self.sex == 0 ? @"男": @"女";

}

@end

當(dāng)然,Domain層并不是必須的喘批,實(shí)際開(kāi)發(fā)中撩荣,需要根據(jù)具體復(fù)雜度和需求來(lái)決定。比如只是純粹的請(qǐng)求展示界面饶深,設(shè)計(jì)過(guò)多的層次結(jié)構(gòu)反而會(huì)增加項(xiàng)目的維護(hù)成本餐曹。同時(shí),Domain層不應(yīng)該存在任何狀態(tài)變量敌厘!

Data數(shù)據(jù)層

ViewModel負(fù)責(zé)展示層邏輯台猴,而Data層則對(duì)應(yīng)數(shù)據(jù)層邏輯,一般以Manager或者Service身份存在俱两,數(shù)據(jù)來(lái)源主要包括Api饱狂、DB或者Cache等。Data數(shù)據(jù)層操作對(duì)象主要為PO持久化對(duì)象宪彩,對(duì)象一旦創(chuàng)建休讳,原則上不可修改

Data數(shù)據(jù)層具有獨(dú)立可測(cè)試性,其不依賴視圖層而存在尿孔。切記不可在Data層操作任何視圖對(duì)象俊柔!

@implementation PersonDBAccess

// Data層不應(yīng)該存在任何視圖相關(guān)代碼

- (NSArray *)fetchPersonModels {

? ? [SVProgressHUD showWithStatus:@"加載中筹麸。。雏婶。"];

}

@end

MVVM奇葩說(shuō)

文章到此物赶,想必各位對(duì)MVVM架構(gòu)已經(jīng)有了大致了解。對(duì)比安卓童鞋對(duì)MVP架構(gòu)的鐘愛(ài)尚骄,iOS童鞋也許更加青睞MVVM块差,拌上ReactiveCocoa或者RxSwift侵续,這道菜可以做的更加絢爛多彩倔丈!當(dāng)然,正如唐巧在文中所言:ReactiveCocoa 和 MVVM 不應(yīng)該被神化状蜗,我們需要保持的是一個(gè)擁抱變化的心需五,以及理性分析的態(tài)度。在新技術(shù)的面前轧坎,不盲從宏邮,也不守舊,一切的決策都應(yīng)該建立在認(rèn)真分析的基礎(chǔ)上缸血,這樣才能應(yīng)對(duì)技術(shù)的變化蜜氨!


寫在文后:

為期兩天的SwiftCon已經(jīng)落幕,雖然離我只有兩站地鐵捎泻,只可惜依然沒(méi)能前往聆聽(tīng)各位大師的技術(shù)分享飒炎,特別還有我同事兼朋友劉冠杉的個(gè)人首秀。雖然笆豁,現(xiàn)在網(wǎng)上也出現(xiàn)了各種不好的聲音郎汪,但是我仍然相信,大多數(shù)分享者還是為此付出了不少心血闯狱,值得我們?yōu)橹恼疲?/i>

個(gè)人技術(shù)的成長(zhǎng)不在一朝一夕煞赢,而是長(zhǎng)年累月的付出積累沉淀的結(jié)果!Swift3.0不久即將發(fā)布哄孤,而我個(gè)人也會(huì)逐漸轉(zhuǎn)移?對(duì)Swift語(yǔ)言的學(xué)習(xí)照筑。與此同時(shí),隨著公司ReactNative項(xiàng)目的上馬瘦陈,我也會(huì)加強(qiáng)對(duì)RN技術(shù)的專研和學(xué)習(xí)中

感謝你的來(lái)訪凝危,你可以Follow我的個(gè)人GitHub,也可以關(guān)注我的新浪微博双饥,下期再見(jiàn)媒抠!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市咏花,隨后出現(xiàn)的幾起案子趴生,更是在濱河造成了極大的恐慌阀趴,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件苍匆,死亡現(xiàn)場(chǎng)離奇詭異刘急,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)浸踩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門叔汁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人检碗,你說(shuō)我怎么就攤上這事据块。” “怎么了折剃?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵另假,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我怕犁,道長(zhǎng)边篮,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任奏甫,我火速辦了婚禮戈轿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阵子。我一直安慰自己思杯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布款筑。 她就那樣靜靜地躺著智蝠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奈梳。 梳的紋絲不亂的頭發(fā)上杈湾,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音攘须,去河邊找鬼漆撞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛于宙,可吹牛的內(nèi)容都是我干的浮驳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼捞魁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼至会!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起谱俭,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤奉件,失蹤者是張志新(化名)和其女友劉穎宵蛀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县貌,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡术陶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了煤痕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梧宫。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摆碉,靈堂內(nèi)的尸體忽然破棺而出塘匣,到底是詐尸還是另有隱情,我是刑警寧澤兆解,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布馆铁,位于F島的核電站跑揉,受9級(jí)特大地震影響锅睛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜历谍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一现拒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧望侈,春花似錦印蔬、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至捐韩,卻和暖如春退唠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荤胁。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工瞧预, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仅政。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓垢油,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親圆丹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子滩愁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容