為何放棄MVC使用MVVM

2017-08-19rickytang0Cocoa開(kāi)發(fā)者社區(qū)

MVC

全稱是 Model View Controller只磷,是模型 (model)-視圖 (view)-控制器 (controller) 的縮寫(xiě)。它表示的是一種常見(jiàn)的客戶端軟件開(kāi)發(fā)框架锨阿。

現(xiàn)在,MVC 已經(jīng)成為主流的客戶端編程框架何荚,在 iOS 開(kāi)發(fā)中毯盈,系統(tǒng)為我們實(shí)現(xiàn)好了公共的視圖類(lèi):UIView,和控制器類(lèi):UIViewController湿刽。大多數(shù)時(shí)候的烁,我們都需要繼承這些類(lèi)來(lái)實(shí)現(xiàn)我們的程序邏輯,因此诈闺,我們幾乎逃避不開(kāi) MVC 這種設(shè)計(jì)模式渴庆。

但是,幾十年過(guò)去了雅镊,我們對(duì)于 MVC 這種設(shè)計(jì)模式真的用得好嗎襟雷?其實(shí)不是的,MVC 這種分層方式雖然清楚仁烹,但是如果使用不當(dāng)耸弄,很可能讓大量代碼都集中在 Controller 之中,讓 MVC 模式變成了 Massive View Controller 模式卓缰。

Controller 的臃腫問(wèn)題何解计呈?

我們來(lái)看看 MVC 這種架構(gòu)的特點(diǎn)砰诵。其實(shí)設(shè)計(jì)模式很多時(shí)候是為了Don't repeat yourself原則來(lái)做的,該原則要求能夠復(fù)用的代碼要盡量復(fù)用捌显,來(lái)保證重用茁彭。在 MVC 這種設(shè)計(jì)模式中,我們發(fā)現(xiàn) View 和 Model 都是符合這種原則的扶歪。

對(duì)于 View 來(lái)說(shuō)理肺,你如果抽象得好,那么一個(gè) App 的動(dòng)畫(huà)效果可以很方便地移植到別的 App 上善镰,而 Github 上也有很多 UI 控件妹萨,這些控件都是在 View 層做了很好的封裝設(shè)計(jì),使得它能夠方便地開(kāi)源給大家復(fù)用炫欺。

對(duì)于 Model 來(lái)說(shuō)乎完,它其實(shí)是用來(lái)存儲(chǔ)業(yè)務(wù)的數(shù)據(jù)的,如果做得好竣稽,它也可以方便地復(fù)用囱怕。比如我當(dāng)時(shí)在做有道云筆記 iPad 版的時(shí)候,我們就直接和 iOS 版復(fù)用了所有的 Model 層的代碼毫别。在創(chuàng)業(yè)做猿題庫(kù)客戶端時(shí)娃弓,iOS 和 iPad 版的 Model 層代碼再次被復(fù)用上了。當(dāng)然岛宦,因?yàn)楹蜆I(yè)務(wù)本身的數(shù)據(jù)意義相關(guān)台丛,Model 層的復(fù)用大多數(shù)是在一個(gè)產(chǎn)品內(nèi)部,不太可能像 View 層那樣開(kāi)源給社區(qū)砾肺。

說(shuō)完 View 和 Model 了挽霉,那我們想想 Controller,Controller 有多少可以復(fù)用的变汪?我們寫(xiě)完了一個(gè) Controller 之后侠坎,可以很方便地復(fù)用它嗎?結(jié)論是:非常難復(fù)用裙盾。在某些場(chǎng)景下实胸,我們可能可以用addSubViewController之類(lèi)的方式復(fù)用 Controller,但它的復(fù)用場(chǎng)景還是非常非常少的番官。

如果我們能夠意識(shí)到 Controller 里面的代碼不便于復(fù)用庐完,我們就能知道什么代碼應(yīng)該寫(xiě)在 Controller 里面了,那就是那些不能復(fù)用的代碼徘熔。在我看來(lái)门躯,Controller 里面就只應(yīng)該存放這些不能復(fù)用的代碼,這些代碼包括:

在初始化時(shí)酷师,構(gòu)造相應(yīng)的 View 和 Model讶凉。

監(jiān)聽(tīng) Model 層的事件染乌,將 Model 層的數(shù)據(jù)傳遞到 View 層。

監(jiān)聽(tīng) View 層的事件缀遍,并且將 View 層的事件轉(zhuǎn)發(fā)到 Model 層慕匠。

如果 Controller 只有以上的這些代碼,那么它的邏輯將非常簡(jiǎn)單域醇,而且也會(huì)非常短。

但是蓉媳,我們卻很難做到這一點(diǎn)譬挚,因?yàn)檫€是有很多邏輯我們不知道寫(xiě)在哪里,于是就都寫(xiě)到了 Controller 中了酪呻,那我們接下來(lái)就看看其它邏輯應(yīng)該寫(xiě)在哪里减宣。

MVVM

Model-View-ViewModel 的簡(jiǎn)寫(xiě)。但在我的理解可以是Model-ViewModel-Controller-View

為什么要這樣樣理解呢玩荠?上面的問(wèn)題Controller的代碼處理太多東西漆腌,導(dǎo)致極其難復(fù)用,而且在后期調(diào)整業(yè)務(wù)阶冈,更換UI等事情上也會(huì)較為困難闷尿。

所以我的建議是將Controller的所有業(yè)務(wù)邏輯都應(yīng)該移動(dòng)到ViewModel層上。具體該做些什么呢女坑?

我們可以將網(wǎng)絡(luò)請(qǐng)求的借口填具,及返回的數(shù)據(jù)寫(xiě)在ViewModel里面,ViewModel再通知Controller來(lái)取得相應(yīng)的數(shù)據(jù)匆骗,并顯示在view上劳景。

還可以將邏輯計(jì)算等方法封裝在ViewModel里面,供Controller調(diào)用碉就。當(dāng)然如果這部分計(jì)算復(fù)用性很高盟广,你還可以封裝到其他公用的類(lèi)里面。

而這個(gè)ViewModel將會(huì)是一個(gè)隨時(shí)可以被其他功能模塊調(diào)用的狀態(tài)瓮钥。而且筋量,一個(gè)Controller可以使用一個(gè)或多個(gè)ViewModel。這樣將會(huì)大大提高代碼分復(fù)用性骏庸,及降低后期的維護(hù)毛甲。

MVVM 在使用當(dāng)中,通常還會(huì)利用雙向綁定技術(shù)具被,使得 Model 變化時(shí)玻募,ViewModel 會(huì)自動(dòng)更新,而 ViewModel 變化時(shí)一姿,View 也會(huì)自動(dòng)變化七咧。而這個(gè)過(guò)程我們可以使用KVO和Notification來(lái)實(shí)現(xiàn)跃惫,但這樣并不是最理想和高效的方式,所以我們需要結(jié)合ReactiveCocoa一起使用艾栋。

ReactiveCocoa是一個(gè)函數(shù)式編程(Functional Programming)和響應(yīng)式編程(React Programming)庫(kù)

函數(shù)式編程(Functional Programming)爆存,函數(shù)也變成一等公民了,可以擁有和對(duì)象同樣的功能蝗砾,例如當(dāng)成參數(shù)傳遞先较,當(dāng)作返回值等〉苛福看看 Swift 語(yǔ)言帶來(lái)的眾多函數(shù)式編程的特性闲勺,就你知道這多 Cool 了。

響應(yīng)式編程(React Programming)扣猫,原來(lái)我們基于事件(Event)的處理方式都弱了菜循,現(xiàn)在是基于輸入(在 ReactiveCocoa 里叫 Signal)的處理方式。輸入還可以通過(guò)函數(shù)式編程進(jìn)行各種 Combine 或 Filter申尤,盡顯各種靈活的處理癌幕。

無(wú)狀態(tài)(Stateless),狀態(tài)是函數(shù)的魔鬼昧穿,無(wú)狀態(tài)使得函數(shù)能更好地測(cè)試勺远。

不可修改(Immutable),數(shù)據(jù)都是不可修改的粤咪,使得軟件邏輯簡(jiǎn)單谚中,也可以更好地測(cè)試。

結(jié)合了RAC庫(kù)寥枝,使得我們編寫(xiě)的程序更加簡(jiǎn)潔高效宪塔,維護(hù)性更高。

總結(jié):

使用MVVM編寫(xiě)代碼囊拜,雖然使層次增加了某筐,但是提高了代碼的復(fù)用性及提高了代碼的可維護(hù)性,再結(jié)合RAC就更加牛B閃閃了冠跷。你們覺(jué)得呢南誊?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蜜托,隨后出現(xiàn)的幾起案子抄囚,更是在濱河造成了極大的恐慌,老刑警劉巖橄务,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幔托,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)重挑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)嗓化,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谬哀,你說(shuō)我怎么就攤上這事刺覆。” “怎么了史煎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵谦屑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我篇梭,道長(zhǎng)伦仍,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任很洋,我火速辦了婚禮,結(jié)果婚禮上隧枫,老公的妹妹穿的比我還像新娘喉磁。我一直安慰自己,他們只是感情好官脓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布协怒。 她就那樣靜靜地躺著,像睡著了一般卑笨。 火紅的嫁衣襯著肌膚如雪孕暇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天赤兴,我揣著相機(jī)與錄音妖滔,去河邊找鬼。 笑死桶良,一個(gè)胖子當(dāng)著我的面吹牛座舍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陨帆,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼曲秉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了疲牵?” 一聲冷哼從身側(cè)響起承二,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纲爸,沒(méi)想到半個(gè)月后亥鸠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缩焦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年读虏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了责静。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盖桥,死狀恐怖灾螃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揩徊,我是刑警寧澤腰鬼,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站塑荒,受9級(jí)特大地震影響熄赡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜齿税,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一彼硫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凌箕,春花似錦拧篮、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至芜壁,卻和暖如春礁凡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慧妄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工顷牌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腰涧。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓韧掩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親窖铡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疗锐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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