移動(dòng)開(kāi)發(fā)架構(gòu)之MVVM模式
MVVM概念的提出和起源
MVVM是Model-View-ViewModel的簡(jiǎn)寫(xiě),最早是由微軟公司提出并運(yùn)用,是MVP(Model-View-Presenter)模式與WPF結(jié)合的應(yīng)用方式時(shí)發(fā)展演變過(guò)來(lái)的一種新型架構(gòu)架構(gòu)。
MVVM概念解釋和要點(diǎn)
一、基本概念
mvvm1.png
- Model:主要為應(yīng)用程序提供數(shù)據(jù)。
- View:還是MVC和MVP中的那個(gè)表示層,同時(shí)實(shí)現(xiàn)UI元素和ViewModel屬性的綁定。
- ViewModel:為View提供數(shù)據(jù)支持。
以胖瘦的觀點(diǎn)來(lái)看,在MVVM中的Model通常是胖Model即有數(shù)據(jù)屬性的定義也有數(shù)據(jù)訪問(wèn)和處理的行為。ViewModel通常是瘦Model只有數(shù)據(jù)屬性,一般含有少量邏輯。
二、基本要點(diǎn)
- View持有ViewModel:在View中通過(guò)綁定的方式關(guān)聯(lián)UI元素和ViewModel的屬性,UI元素的屬性變化和ViewMode的數(shù)據(jù)屬性進(jìn)行雙向影響。
- ViewModel持有Model:Model為ViewModel提供數(shù)據(jù)支持,同時(shí)ViewModel的數(shù)據(jù)屬性變化也會(huì)影響Model上,用于數(shù)據(jù)提交等。
Model和ViewModel的功能區(qū)別在于,ViewModel是View提供數(shù)據(jù)支持的,其結(jié)構(gòu)和View保持一致。Model來(lái)源于業(yè)務(wù)處理,保持業(yè)務(wù)數(shù)據(jù)的基本關(guān)聯(lián)和完整性。 - 當(dāng)Model層結(jié)束查詢或者運(yùn)算時(shí)將結(jié)果更新到ViewModel層,ViewModel層因?yàn)榇嬖诤蚔iew的綁定,使得UI層得到通知更新,體現(xiàn)了數(shù)據(jù)驅(qū)動(dòng)界面的思想。
三、優(yōu)點(diǎn)
MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model)有幾大優(yōu)點(diǎn):
- 低耦合。通過(guò)ViewMode隔離了View和Model,使得View和Model彼此獨(dú)立,一方的變化和修改不會(huì)影響到另外一方。
- 可重用性。一個(gè)Model和ViewModel可以服務(wù)于很多View。
- 獨(dú)立開(kāi)發(fā)。讓UI開(kāi)發(fā)工作和業(yè)務(wù)處理工作分開(kāi),適合團(tuán)隊(duì)工作。
- 可測(cè)試。界面素來(lái)是比較難于測(cè)試的,而現(xiàn)在測(cè)試可以針對(duì)ViewModel來(lái)寫(xiě)。
MVVM的經(jīng)典范例WPF
MVVM并不是一個(gè)新的概念,目前由于在移動(dòng)開(kāi)發(fā)的運(yùn)用又被大家廣泛討論。要講解MVVM無(wú)論是從起源、概念的定義和***運(yùn)用都不可能離開(kāi)WPF。
MVVM和WPF結(jié)合時(shí)除了滿足MVVM基本架構(gòu)模式外,由于在UI編輯時(shí)(Xaml)支持多模式的數(shù)據(jù)和事件綁定***實(shí)現(xiàn)View和ViewModel的對(duì)接,同時(shí)轉(zhuǎn)換器和觸發(fā)器的運(yùn)用又保證了其靈活性。所以無(wú)論是要深入的了解MVVM還是尋求以MVVM模式構(gòu)建產(chǎn)品,都建議大家仔細(xì)的研讀WPF相關(guān)開(kāi)發(fā)知識(shí),是個(gè)很好的參照。
MVVM在移動(dòng)開(kāi)發(fā)中的運(yùn)用
移動(dòng)開(kāi)發(fā)中運(yùn)用MVVM時(shí),view和viewcontroller(安卓:局文件和Activity)正式聯(lián)系在一起,我們把它們視為一個(gè)組件。視圖view仍然不能直接引用模型model,當(dāng)然controller也不能。相反,他們引用視圖模型viewmodel。
MVVM.png
用戶輸入驗(yàn)證邏輯,視圖顯示邏輯處理通常還是要放在ViewController進(jìn)行,不過(guò)對(duì)于視圖的控制盡可能通過(guò)ViewModel的數(shù)據(jù)屬性去影響而不是直接操作。發(fā)起網(wǎng)絡(luò)請(qǐng)求和數(shù)據(jù)存貯等處理可以放在Model進(jìn)行但是不可以有任何視圖本身的引用。( model中使用 #import UIKit.h)
展示邏輯(presentation logic)可以放在了view model中(比如model的值映射到一個(gè)格式化的字符串),視圖控制器本身就會(huì)不再臃腫。使用MVVM的App是高度可測(cè)試的;因?yàn)関iew model包含了所有的展示邏輯并且不會(huì)引用view,所以它可以通過(guò)編程方式充分測(cè)試。
在android開(kāi)發(fā)方面目前已有像 RoboBinding 這樣的架構(gòu),可以實(shí)現(xiàn)在布局文件中完成與ViewModel的綁定工作。IOS中通常建議MVVM與 ReactiveCocoa 聯(lián)合使用。
Goo框架:IOS的MVVM模式的實(shí)現(xiàn)
ReactiveCocoa作為響應(yīng)式變成概念上確實(shí)很火熱也備受推崇。從架構(gòu)設(shè)計(jì)思想學(xué)習(xí)的角度,個(gè)人也是很喜歡的。但是主導(dǎo)在產(chǎn)品開(kāi)發(fā)中運(yùn)用還是不愿意的。俗話說(shuō)喜歡一件事物原因有很多種,不喜歡的原因只需要一個(gè),Reactive有別于傳統(tǒng)思路和基本IOS開(kāi)發(fā)思維需要一定代價(jià)的的學(xué)習(xí)代價(jià)是每個(gè)團(tuán)隊(duì)都不愿意接受的。
Goo是什么?
簡(jiǎn)單概括一句話:Goo是MVVM模式在IOS開(kāi)發(fā)中的具體實(shí)現(xiàn)。使用Goo開(kāi)發(fā)不會(huì)改變現(xiàn)有的開(kāi)發(fā)習(xí)慣,在一個(gè)開(kāi)發(fā)中可以根據(jù)具體場(chǎng)景的便利性考慮是否使用Goo,總之Goo具有小巧、靈活和易用等的特點(diǎn)。
舉個(gè)栗子
Goo.gif
如圖運(yùn)行效果,實(shí)現(xiàn)通過(guò)實(shí)現(xiàn)如下幾個(gè)小功能來(lái)對(duì)Goo進(jìn)行展示。
1:在TextField中輸入數(shù)據(jù)下面的Label同步顯示
2:?jiǎn)螕糇髠?cè)按鈕改變數(shù)據(jù)內(nèi)容,同時(shí)影響TextField和Label顯示內(nèi)容
3:?jiǎn)螕粲覀?cè)按鈕該數(shù)據(jù)屬性,同時(shí)影響TextField和Label的不同屬性。
接下來(lái)看使用Goo來(lái)實(shí)現(xiàn)的具體代碼情況
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _vm = [TrialDataVM using]; _vm.text = @"123"; [self.inputText bindingWithProperty:@"backgroundColor" withObject:_vm withDataSource:@"backgroundColor" withBindingMode:TwoWay]; [self.inputText bindingWithProperty:@"text" withObject:_vm withDataSource:@"text" withBindingMode:TwoWay]; [self.hineLbl bindingWithProperty:@"text" withObject:_vm withDataSource:@"text" withBindingMode:OneWay]; [self.hineLbl bindingWithProperty:@"textColor" withObject:_vm withDataSource:@"backgroundColor" withBindingMode:OneWay]; } - (IBAction)clickAction:(id)sender { _vm.text = @"456";} - (IBAction)otherAction:(id)sender { _vm.backgroundColor =[UIColor redColor];}
不用驚訝!代碼就這幾行。
通過(guò)bindingWithProperty方法來(lái)完成控件和ViewModel的綁定工作,后續(xù)只改動(dòng)ViewModel其自動(dòng)會(huì)影響UI元素的屬性。
Goo是本人依據(jù)MVVM模式手開(kāi)發(fā)的IOS下開(kāi)源框架,后續(xù)會(huì)專門寫(xiě)文章來(lái)進(jìn)行對(duì)其進(jìn)行介紹,同時(shí)代碼也會(huì)在Github共享。希望感興趣的朋友加入將其繼續(xù)完善和推廣。