MVVM和MVC的區(qū)別
1. MVC
MVC的弊端
-
厚重的View Controller
M:模型model的對象通常非常的簡單。根據(jù)Apple的文檔,model應(yīng)包括數(shù)據(jù)和操作數(shù)據(jù)的業(yè)務(wù)邏輯。而在實(shí)踐中,model層往往非常薄,不管怎樣,model層的業(yè)務(wù)邏輯不應(yīng)被拖入到controller。
V:視圖view通常是UIKit控件(component,這里根據(jù)習(xí)慣譯為控件)或者編碼定義的UIKit控件的集合。View的如何構(gòu)建(PS:IB或者手寫界面)何必讓Controller知曉,同時(shí)View不應(yīng)該直接引用model(PS:現(xiàn)實(shí)中,你懂的!),并且僅僅通過IBAction事件引用controller。業(yè)務(wù)邏輯很明顯不歸入view,視圖本身沒有任何業(yè)務(wù)。
C:控制器controller。Controller是app的“膠水代碼”:協(xié)調(diào)模型和視圖之間的所有交互。控制器負(fù)責(zé)管理他們所擁有的視圖的視圖層次結(jié)構(gòu),還要響應(yīng)視圖的loading、appearing、disappearing等等,同時(shí)往往也會充滿我們不愿暴露的model的模型邏輯以及不愿暴露給視圖的業(yè)務(wù)邏輯。網(wǎng)絡(luò)數(shù)據(jù)的請求及后續(xù)處理,本地?cái)?shù)據(jù)庫操作,以及一些帶有工具性質(zhì)輔助方法都加大了Massive View Controller的產(chǎn)生。
遺失(無處安放)的網(wǎng)絡(luò)邏輯
蘋果使用的MVC的定義是這么說的:所有的對象都可以被歸類為一個model,一個view,或是一個controller。
你可能試著把它放在Model對象里,但是也會很棘手,因?yàn)榫W(wǎng)絡(luò)調(diào)用應(yīng)該使用異步,這樣如果一個網(wǎng)絡(luò)請求比持有它的model生命周期更長,事情將變的復(fù)雜。顯然View里面做網(wǎng)絡(luò)請求那就更格格不入了,因此只剩下Controller了。若這樣,這又加劇了Massive View Controller的問題。若不這樣,何處才是網(wǎng)絡(luò)邏輯的家呢?
- 較差的可測試性
由于View Controller混合了視圖處理邏輯和業(yè)務(wù)邏輯,分離這些成分的單元測試成了一個艱巨的任務(wù)。
2. MVVM
一種可以很好地解決Massive View Controller
問題的辦法就是將 Controller 中的展示邏輯抽取出來,放置到一個專門的地方,而這個地方就是 viewModel
。MVVM衍生于MVC,是對 MVC 的一種演進(jìn),它促進(jìn)了 UI 代碼與業(yè)務(wù)邏輯的分離。它正式規(guī)范了視圖和控制器緊耦合的性質(zhì),并引入新的組件。他們之間的結(jié)構(gòu)關(guān)系如下:
2.1 MVVM 的基本概念
- 在
MVVM
中,view
和view controller
正式聯(lián)系在一起,我們把它們視為一個組件 -
view
和view controller
都不能直接引用model
,而是引用視圖模型(viewModel
) -
viewModel
是一個放置用戶輸入驗(yàn)證邏輯,視圖顯示邏輯,發(fā)起網(wǎng)絡(luò)請求和其他代碼的地方 - 使用
MVVM
會輕微的增加代碼量,但總體上減少了代碼的復(fù)雜性
2.2 MVVM 的注意事項(xiàng)
-
view
引用viewModel
,但反過來不行(即不要在viewModel
中引入#import UIKit.h
,任何視圖本身的引用都不應(yīng)該放在viewModel
中)(PS:基本要求,必須滿足) -
viewModel
引用model
,但反過來不行* MVVM 的使用建議 -
MVVM
可以兼容你當(dāng)下使用的MVC
架構(gòu)。 -
MVVM
增加你的應(yīng)用的可測試性。 -
MVVM
配合一個綁定機(jī)制效果最好(PS:ReactiveCocoa你值得擁有)。 -
viewController
盡量不涉及業(yè)務(wù)邏輯,讓viewModel
去做這些事情。 -
viewController
只是一個中間人,接收view
的事件、調(diào)用viewModel
的方法、響應(yīng)viewModel
的變化。 -
viewModel
絕對不能包含視圖view(UIKit.h)
,不然就跟view
產(chǎn)生了耦合,不方便復(fù)用和測試。 -
viewModel
之間可以有依賴。 -
viewModel
避免過于臃腫,否則重蹈Controller
的覆轍,變得難以維護(hù)。
2.3 MVVM 的優(yōu)勢
- 低耦合:
View
可以獨(dú)立于Model
變化和修改,一個viewModel
可以綁定到不同的View
上 - 可重用性:可以把一些視圖邏輯放在一個
viewModel
里面,讓很多view
重用這段視圖邏輯 - 獨(dú)立開發(fā):開發(fā)人員可以專注于業(yè)務(wù)邏輯和數(shù)據(jù)的開發(fā)
viewModel
,設(shè)計(jì)人員可以專注于頁面設(shè)計(jì) - 可測試:通常界面是比較難于測試的,而
MVVM
模式可以針對viewModel
來進(jìn)行測試
2.4 MVVM 的弊端
- 數(shù)據(jù)綁定使得
Bug
很難被調(diào)試。你看到界面異常了,有可能是你View
的代碼有Bug
,也可能是Model
的代碼有問題。數(shù)據(jù)綁定使得一個位置的Bug
被快速傳遞到別的位置,要定位原始出問題的地方就變得不那么容易了。 - 對于過大的項(xiàng)目,數(shù)據(jù)綁定和數(shù)據(jù)轉(zhuǎn)化需要花費(fèi)更多的內(nèi)存(成本)。主要成本在于:
- 數(shù)組內(nèi)容的轉(zhuǎn)化成本較高:數(shù)組里面每項(xiàng)都要轉(zhuǎn)化成
Item
對象,如果Item對象中還有類似數(shù)組,就很頭疼。 - 轉(zhuǎn)化之后的數(shù)據(jù)在大部分情況是不能直接被展示的,為了能夠被展示,還需要第二次轉(zhuǎn)化。
- 只有在API返回的數(shù)據(jù)高度標(biāo)準(zhǔn)化時(shí),這些對象原型(
Item
)的可復(fù)用程度才高,否則容易出現(xiàn)類型爆炸,提高維護(hù)成本。 - 調(diào)試時(shí)通過對象原型查看數(shù)據(jù)內(nèi)容不如直接通過
NSDictionary/NSArray
直觀。 - 同一API的數(shù)據(jù)被不同View展示時(shí),難以控制數(shù)據(jù)轉(zhuǎn)化的代碼,它們有可能會散落在任何需要的地方。
3. 總結(jié)
MVC
的設(shè)計(jì)模式也并非是病入膏肓,無藥可救的架構(gòu),最起碼目前MVC設(shè)計(jì)模式仍舊是iOS開發(fā)的主流框架,存在即合理。針對文章所述的弊端,我們依舊有許多可行的方法去避免和解決,從而打造一個輕量級的ViewController
。MVVM
是MVC
的升級版,完全兼容當(dāng)前的MVC架構(gòu),MVVM雖然促進(jìn)了UI 代碼與業(yè)務(wù)邏輯的分離,一定程度上減輕了ViewController
的臃腫度,但是View
和ViewModel
之間的數(shù)據(jù)綁定使得 MVVM變得復(fù)雜和難用了,如果我們不能更好的駕馭兩者之間的數(shù)據(jù)綁定,同樣會造成Controller 代碼過于復(fù)雜,代碼邏輯不易維護(hù)的問題。一個輕量級的
ViewController
是基于MVC
和MVVM
模式進(jìn)行代碼職責(zé)的分離而打造的。MVC和MVVM有優(yōu)點(diǎn)也有缺點(diǎn),但缺點(diǎn)在他們所帶來的好處面前時(shí)不值一提的。他們的低耦合性,封裝性,可測試性,可維護(hù)性和多人協(xié)作便利大大提高了開法效率。同時(shí),我們需要保持的是一個擁抱變化的心,以及理性分析的態(tài)度。在新技術(shù)的面前,不盲從,也不守舊,一切的決策都應(yīng)該建立在認(rèn)真分析的基礎(chǔ)上,這樣才能應(yīng)對技術(shù)的變化。
更多:iOS面試題合集