也談MVVM

先說MVC吧

MVC,全稱是 Model View Controller邮破,是模型 (model)-視圖 (view)-控制器 (controller) 的縮寫。它表示的是一種常見的客戶端軟件開發(fā)框架;
MVC這個概念最早出現(xiàn)在上個世紀(jì)八十年代(目測本文的讀者都還沒有出生,當(dāng)然筆者也沒有出生)被提出,之后被廣泛的應(yīng)用于各類軟件開發(fā)中.
iOS開發(fā)也不例外,iOS的系統(tǒng)架構(gòu)就是典型的MVC,并且為我們實現(xiàn)了V層和C層的基礎(chǔ),然后開發(fā)者根據(jù)相應(yīng)的數(shù)據(jù)補充M.這一切看起都很合理,而且開發(fā)者也一直都這么做著,并沒有什么不妥
嗯,是的,沒毛病...

但是事實真的如此么?
事實是,很多維護者會抱怨前人的代碼多爛多爛,真的沒法看,設(shè)計模式一塌糊涂等等;
這時候的MVC可能會變成(Massive View Controller),controller里面塞滿了各類業(yè)務(wù)代碼,多大上千行,甚至更多,如果注釋寫的好一些,勉強能看,如果沒有注釋...
為什么會這樣?這里的原因太多了,比如有些開發(fā)者在做iOS之前并沒有聽說過MVC,有些即使知道MVC,也根本無法明確MVC到底干嘛的?面試官經(jīng)常會問到這個問題,而得到的答案也僅僅是解釋MVC概念之類,很少有人會在解釋完概念之后再去仔細(xì)的闡述一下結(jié)構(gòu)設(shè)計,代碼規(guī)范之類...

下面我們仔細(xì)剖析一下,到底該如何MVC?

真正的MVC

我們來看看 MVC 這種架構(gòu)的特點。其實設(shè)計模式很多時候是為了 Don't repeat yourself 原則來做的饲鄙,該原則要求能夠復(fù)用的代碼要盡量復(fù)用谬以,來保證重用强饮。在 MVC 這種設(shè)計模式中,我們發(fā)現(xiàn) ViewModel 都是符合這種原則的为黎。

對于View來說邮丰,你如果抽象得好,那么一個App的動畫效果可以很方便地移植到別的App上铭乾,而Github上也有很多UI控件剪廉,這些控件都是在View層做了很好的封裝設(shè)計,使得它能夠方便地開源給大家復(fù)用炕檩。

對于Model來說斗蒋,它其實是用來存儲業(yè)務(wù)的數(shù)據(jù)的,如果做得好笛质,它也可以方便地復(fù)用泉沾。比如我當(dāng)時在做有道云筆記 iPad 版的時候,我們就直接和iOS版復(fù)用了所有的Model層的代碼妇押。在創(chuàng)業(yè)做猿題庫客戶端時,iOSiPad 版的 Model 層代碼再次被復(fù)用上了跷究。當(dāng)然,因為和業(yè)務(wù)本身的數(shù)據(jù)意義相關(guān)敲霍,Model 層的復(fù)用大多數(shù)是在一個產(chǎn)品內(nèi)部俊马,不太可能像 View 層那樣開源給社區(qū)丁存。

說完 ViewModel 了,那我們想想 Controller柴我,Controller 有多少可以復(fù)用的解寝?我們寫完了一個 Controller 之后,可以很方便地復(fù)用它嗎屯换?結(jié)論是:非常難復(fù)用编丘。在某些場景下,我們可能可以用addSubViewController 之類的方式復(fù)用 Controller彤悔,但它的復(fù)用場景還是非常非常少的嘉抓。

如果我們能夠意識到 Controller 里面的代碼不便于復(fù)用,我們就能知道什么代碼應(yīng)該寫在 Controller 里面了晕窑,那就是那些不能復(fù)用的代碼抑片。在我看來,Controller 里面就只應(yīng)該存放這些不能復(fù)用的代碼杨赤,這些代碼包括:

  • 在初始化時敞斋,構(gòu)造相應(yīng)的 View 和 Model。
  • 監(jiān)聽 Model 層的事件疾牲,將 Model 層的數(shù)據(jù)傳遞到 View 層植捎。
  • 監(jiān)聽 View 層的事件,并且將 View 層的事件轉(zhuǎn)發(fā)到 Model 層阳柔。

MVC反面教材

直接上代碼吧:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
    cell.textLabel?.text = "二狗子"
    cell.imageView?.image = UIImage(named: "")
    return cell
}

上面這段代碼,咋一看也沒啥,因為只有6行而已,但是這是因為上面的cell數(shù)據(jù)加載很簡單,只有一個textimage,但實際開發(fā)中,我們的數(shù)據(jù)可不是這樣的,如果是新浪微博那種cell我想,單單是cell的數(shù)據(jù)加載都能寫個上百行;所以這種寫法是完全違反MVC原則的,因為你在C里面干了V的事情, C只應(yīng)該做數(shù)據(jù)傳遞;所以,嚴(yán)格遵循MVC原則的寫法是,不管cell的數(shù)據(jù)加載多么負(fù)責(zé),代碼都應(yīng)該是下面這樣的:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
    cell.userModel = dataModel[indexPath.row]
    return cell
}

如果你的tableview是個標(biāo)準(zhǔn)的反面教材,請在評論區(qū)留下你的大名??

這里只是簡單的做了一些代碼結(jié)構(gòu)的調(diào)整,但是確實符合了MVC原則,但是在controller中往往不止這些東西,controller最頭疼的問題,就是網(wǎng)絡(luò)請求問題,因為復(fù)雜的界面會涉及到很多數(shù)據(jù)請求,而這些請求也會伴隨著界面和數(shù)據(jù)的變化,這些邏輯寫上去,那么controller的代碼量瞬間就上去了,幾個版本迭代過去,你懂的!所以,達到上千行只是時間問題?

何解?
在網(wǎng)上關(guān)于這個問題的答案有很多,比如分離網(wǎng)絡(luò)業(yè)務(wù)層,直接放到一個專門的業(yè)務(wù)模塊里面,MVVM就是在這種情況下衍生出來的.

MVVM

MVVM的歷史,這里就不贅述了,感興趣的同學(xué)直接百度,一大把,先看看一張基本上只要談到MVVM都會放的一張圖:

MVVM結(jié)構(gòu)圖

上面這張圖,我想很多人肯定不止一次看到過

這個圖準(zhǔn)確的描述了什么是MVVM:一個MVC的增強版,讓viewviewcontroller直接結(jié)合在一起,使用ViewModel進行鏈接,并將邏輯從controller里面移出放到ViewModel;MVVM聽起來很復(fù)雜,但是他本質(zhì)還是MVC,只不過在結(jié)構(gòu)上做了調(diào)整;這樣viewmodel徹底解耦了,那么這個時候他們之間的通信會變得有些奇怪了,因為他們中間跨越了一個層,所以在MVVM的使用當(dāng)中,通常會利用雙向綁定技術(shù),使得Model的變化能同步更新到View
那么這里就得提到一個框架:ReactiveCocoa(swiftObjective - C都支持,但是在Swift上更推薦使用RxSwift);

ReactiveCocoa是一個基于Cocoa封裝的函數(shù)響應(yīng)式框架,使用它可以輕松的實現(xiàn)數(shù)據(jù)的綁定;所以,每每談到MVVM的時候,總會提到它;但ReactiveCocoa可以不想其他三方框架那般,看看Document就可以開心的擼起來了,ReactiveCocoaDocument都能寫成一本厚厚的書了,而且最關(guān)鍵的是,它的編程思想,函數(shù)式,響應(yīng)式,數(shù)據(jù)流...
還有它那魔性的語法.

當(dāng)然了ReactiveCocoa也提供了很多便捷:

  • 函數(shù)式,提供了很多函數(shù)式操作(對于Objective - C來說,Swift本身自帶)
  • 數(shù)據(jù)綁定,很多時候可以代替KVO,delegate
  • 動態(tài)聲明

更多信息可以去官網(wǎng)閱讀相關(guān)文檔,本文這里不做太多探討;

要換MVVM?

既然MVVM有那么多好處,為何不換?
在移動開發(fā)領(lǐng)域,MVVM提出也不短了,可大部分項目還是使用MVC,只有少部分項目會用;還有一部分項目會有專門的架構(gòu)師,為項目設(shè)計架構(gòu),他們會搞出一些大家都不懂的東西,然后在某個分享會上分享給大家;
但是!
我們要想清楚,你的項目真的需要MVVM么?
不一定吧?
如果你的項目本來就不復(fù)雜,為何要換?MVC就挺好的,別聽那些"分享"
筆者不是說那些分享不好,好,確實好,但,那是在他們的項目上用呀,他們都是就職于BAT這樣的大廠的

一笑而過?

通過上面的閱讀,相信你已經(jīng)對MVCMVVM有所了解,那么問題來了.

該用什么?

相信,很多iOS開發(fā)者在找工作面試的時候都被問過MVVM,基本上都快成了必問點了

我們不好說,哪個更好,哪個更適合.根據(jù)自己的情況選擇
MVVM的學(xué)習(xí)路線相對要難很多,但是空閑的時候嘗試一下也是個不錯的實踐,其中收獲必定不小的
至少下次吹叛媸啵或面試的時候,你也多一些談資不是?

生命不息,折騰不止...
I'm not a real coder, but i love it so much!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舌剂,一起剝皮案震驚了整個濱河市济锄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌霍转,老刑警劉巖荐绝,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異避消,居然都是意外死亡低滩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門沾谓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來委造,“玉大人,你說我怎么就攤上這事均驶』枵祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵妇穴,是天一觀的道長爬虱。 經(jīng)常有香客問我隶债,道長,這世上最難降的妖魔是什么跑筝? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任死讹,我火速辦了婚禮,結(jié)果婚禮上曲梗,老公的妹妹穿的比我還像新娘赞警。我一直安慰自己,他們只是感情好虏两,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布愧旦。 她就那樣靜靜地躺著,像睡著了一般定罢。 火紅的嫁衣襯著肌膚如雪笤虫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天祖凫,我揣著相機與錄音琼蚯,去河邊找鬼。 笑死惠况,一個胖子當(dāng)著我的面吹牛遭庶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稠屠,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼罚拟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了完箩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤拉队,失蹤者是張志新(化名)和其女友劉穎弊知,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體粱快,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡秩彤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了事哭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漫雷。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鳍咱,靈堂內(nèi)的尸體忽然破棺而出降盹,到底是詐尸還是另有隱情,我是刑警寧澤谤辜,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布蓄坏,位于F島的核電站价捧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏涡戳。R本人自食惡果不足惜结蟋,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渔彰。 院中可真熱鬧嵌屎,春花似錦、人聲如沸恍涂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乳丰。三九已至掌测,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間产园,已是汗流浹背汞斧。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留什燕,地道東北人粘勒。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像屎即,于是被迫代替她去往敵國和親庙睡。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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