久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

iOS架構(gòu)模式——MV(X)的理解與實戰(zhàn)

 天堂菊香 2018-05-16


作為一個iOS程序員,MVC一定是我們耳熟能詳?shù)囊环N架構(gòu)模式,,而且當你的項目規(guī)模不大的時候,,MVC也確實有它的優(yōu)勢,它的開發(fā)效率確實是足夠高,。但當你的項目發(fā)展的一定的規(guī)模,,你會發(fā)現(xiàn)傳統(tǒng)的MVC模式會導致C層代碼量劇增,維護困難等一系列問題,,這個時候我們就需要考慮一些其它模式了,。

MV(X)的基本要素


常用的架構(gòu)模式

  • MVC

  • MVVM

  • MVP

  • VIPER


前面三種模式都由三個模塊組成:

  • Models —— 數(shù)據(jù)層,負責數(shù)據(jù)的處理,。

  • Views —— 展示層,,即所有的UI

  • Controller/Presenter/ViewModele(控制器/展示器/視圖模型)——它們負責View與Mode之間的調(diào)配

MVC

傳統(tǒng)的MVC


我們所熟知的MVC其實Apple給我們提供的Cocoa MVC,但其實MVC最先產(chǎn)生于Web,,它原來的樣子應該是這樣的


傳統(tǒng)MVC


在這種架構(gòu)下,,View是無狀態(tài)的,在Model變化的時候它只是簡單的被Controller重繪,,比如網(wǎng)頁中你點擊了一個新的鏈接,,整個頁面就重新加載。盡管這種MVC在iOS應該里面可以實現(xiàn),,但是由于MVC的三個模塊都緊密耦合了,,每一個模塊都和其它兩種模塊有聯(lián)系,所以即便是實現(xiàn)了也沒有什么意義,。這種耦合還降低了它們的可重用性,,所以,傳統(tǒng)的MVC在iOS中可以舍棄了,。

Apple的MVC

Cocoa MVC


Apple提供的MVC中,,View和Model之間是相互獨立的,它們只通過Controller來相互聯(lián)系,??上У氖荂ontroller得重用性太差,因為我們一般都把冗雜的業(yè)務邏輯放在了Controller中,。

現(xiàn)實中,,我們的MVC一般是這樣的

現(xiàn)實MVC

為什么會這樣呢?主要還是因為我們的UIViewController它本身就擁有一個VIew,這個View是所有視圖的根視圖,,而且View的生命周期也都由Controoler負責管理,,所以View和Controller是很難做到相互獨立的。雖然你可以把控制器里的一些業(yè)務邏輯和數(shù)據(jù)轉(zhuǎn)換工作交給Model,,但是你卻沒有辦法將一些工作讓View來分攤,,因為View的主要職責只是將用戶的操作行為交給Controller去處理而已。于是Controller最終就變成了所有東西的代理和數(shù)據(jù)源,,甚至還有網(wǎng)絡請求.....還有......所以我們寫的Controller代碼量一般都是非常大的,,隨著當業(yè)務需求的增加,Controller的代碼量會一直增長,,而相對來說View和Model的代碼量就比較穩(wěn)定,,所以也有人把MVC叫做Massive View Controller,因為Controller確實顯得有些臃腫,。

在這里關(guān)于Model的劃分,,其實有一個胖Model和瘦Model之分,它們的差別主要就是把Controller的部分數(shù)據(jù)處理職責交給了胖Model,。

胖Model(Fat Model):

胖Model包含了部分弱業(yè)務邏輯。胖Model要達到的目的是,,Controller從胖Model這里拿到數(shù)據(jù)之后,,不用做額外的操作或者只做非常少的操作就能將數(shù)據(jù)應用在View上。
FatModel做了這些弱業(yè)務之后,,Controller可以變得相對skinny一點,,它只需要關(guān)注強業(yè)務代碼。而強業(yè)務變動的可能性要比弱業(yè)務大得多,,弱業(yè)務相對穩(wěn)定,,所以弱業(yè)務塞給Model不會有太大問題。另一方面,,弱業(yè)務重復出現(xiàn)的頻率要大于強業(yè)務,,對復用性要求更高,如果這部分業(yè)務寫在Controller,,會造成代碼冗余,,類似的代碼會灑得到處都是,而且一旦弱業(yè)務有修改,,你就會需要修改所有地方,。如果塞到了Model中,就只需要改Model就夠了,。
但是胖Mpdel也不是就是沒有缺點的,,它的缺點就在于胖Model相對比較難移植,雖然只是包含弱業(yè)務,,但是它畢竟也是業(yè)務,,遷移的時候很容易拔出羅布帶出泥,,也就是說它耦合了它的業(yè)務。而且軟件是會成長的,,F(xiàn)atModel也很有可能隨著軟件的成長越來越Fat,,最后難以維護。

瘦Model(Slim Model):

瘦Model只負責業(yè)務數(shù)據(jù)的表達,,所有業(yè)務無論強弱一律人給Controller,。瘦Model要達到的目的是,盡一切可能去編寫細粒度Model,,然后配套各種helper類或者方法來對弱業(yè)務做抽象,,強業(yè)務依舊交給Controller。
由于Slim Model跟業(yè)務完全無關(guān),,它的數(shù)據(jù)可以交給任何一個能處理它數(shù)據(jù)的Helper或其他的對象,,來完成業(yè)務。在代碼遷移的時候獨立性很強,,很少會出現(xiàn)拔出蘿卜帶出泥的情況,。另外,由于SlimModel只是數(shù)據(jù)表達,,對它進行維護基本上是0成本,,軟件膨脹得再厲害,SlimModel也不會大到哪兒去,。缺點就在于,,Helper這種做法也不見得很好,由于Model的操作會出現(xiàn)在各種地方,,SlimModel很容易出現(xiàn)代碼重復,,在一定程度上違背了DRY(Don’t Repeat Yourself)的思路,Controller仍然不可避免在一定程度上出現(xiàn)代碼膨脹,。

綜上所述,,Cocoa MVC在各方面的表現(xiàn)如下:

  • 劃分 - View 和 Model 確實是實現(xiàn)了分離,但是 View 和 Controller 耦合的太 厲害

  • 可測性 - 因為劃分的不夠清楚,,所以能測的基本就只有 Model 而已

  • 易用 - 相較于其他模式,,它的代碼量最少。而且基本上每個人都很熟悉它,,即便是沒太多經(jīng)驗的開發(fā)者也能維護,。

MVP

MVP


看起來和Cocoa MVC很像,也確實很像,。但是,,在MVC中View和COntroller是緊密耦合的,而在MVP中,Presenter完全不關(guān)注ViewController的生命周期,,而且View也能被簡單mock出來,,所以在Presenter里面基本沒有什么布局相關(guān)的代碼,它的職責只是通過數(shù)據(jù)和狀態(tài)更新View,。
而且在MVP中,,UIVIewController的那些子類其實是屬于View的。這樣就提供了更好的可測性,,只是開發(fā)速度會更高,,因為你必須手動去創(chuàng)建數(shù)據(jù)和綁定事件。

下面我寫了個簡單的Demo

MVPDemo


由于這里主要是學習架構(gòu)模式思想,,所以我的命名簡單粗暴,,希望大家理解。

界面1


界面也很簡單,,就是通過點擊按鈕修改兩個label顯示的內(nèi)容

Model很簡單,,就是一個數(shù)據(jù)結(jié)構(gòu),但在實際應用中,,你可以將網(wǎng)絡請求等一些數(shù)據(jù)處理放在這里

@interface Model : NSObject
@property (nonatomic, strong) NSString *first;
@property (nonatomic, strong) NSString *second;
@end


要讓Presenter和View通信,,所以我們定義一個協(xié)議,以實現(xiàn)Presenter向View發(fā)送命令

@protocol MyProtocol <NSObject>
- (void)setFirst:(NSString *)first;
- (void)setSecond:(NSString *)second;
@end


view/VIewController,,實現(xiàn)該協(xié)議

.h
@interface ViewController : UIViewController
@property (nonatomic, strong) UILabel *firstLabel;
@property (nonatomic, strong) UILabel *secondLabel;
@property (nonatomic, strong) UIButton *tapButton;
@end
.m主要代碼
- (void)viewDidLoad {
   [super viewDidLoad];
   [self.view addSubview:self.firstLabel];
   [self.view addSubview:self.secondLabel];
   [self.view addSubview:self.tapButton];
   self.presenter = [Presenter new];
   [self.presenter attachView:self];
}
- (void)buttonClicked{
   [self.presenter reloadView];
}
- (void)setFirst:(NSString *)first{
   self.firstLabel.text = first;
}
- (void)setSecond:(NSString *)second{
   self.secondLabel.text = second;
}


Presenter

.h
@interface Presenter : NSObject
- (void)attachView:(id <MyProtocol>)attachView;
- (void)reloadView;
@end
.m
@interface Presenter()
@property (nonatomic, weak) id <MyProtocol> view;
@property (nonatomic, strong) Model *model;
@end
@implementation Presenter
- (instancetype)init
{
   self = [super init];
   if (self) {
       self.model = [Model new];
       self.model.first = @'first';
       self.model.second = @'second';
   }
   return self;
}
- (void)attachView:(id<MyProtocol>)attachView{
   self.view = attachView;
}
- (void)reloadView{
   //可以在這里做一些數(shù)據(jù)處理
   [self.view setFirst:self.model.first];
   [self.view setSecond:self.model.second];
}
@end


這里只是一個簡單的Demo,,其實思想很簡單,就是講業(yè)務邏輯交給Presenter,,而Presenter以命令的形式來控制View。

一些說明:


MVP架構(gòu)擁有三個真正獨立的分層,,所以在組裝的時候會有一些問題,,而MVP也成了第一個披露這種問題的架構(gòu),因為我們不想讓View知道Model的信息,,所以在當前的Controller去組裝是不正確的,,我們應該在另外的地方完成組裝。比如我們可以創(chuàng)建一個應用層的Router服務,,讓它來負責組裝和View-to-View的轉(zhuǎn)場,。這個問題下很多模式中都存在。

下面總結(jié)一下MVP的各方面表現(xiàn):

  • 劃分——我們把大部分職責都分配到了Presenter和Model里面,,而View基本不需要做什么

  • 可測性——我們可以通過View來測試大部分業(yè)務邏輯

  • 易用——代碼量差不多是MVC架構(gòu)的兩倍,,但是MVP的思路還是蠻清晰的


另外,MVP還有一個變體,,它的不同主要就是添加了數(shù)據(jù)綁定,。這個版本的MVP的View和Model直接綁定,而Presenter仍然繼續(xù)處理View上的用戶操作,控制View的顯示變化,。這種架構(gòu)和傳統(tǒng)的MVC類似,,所以我們基本可以舍棄。

MVVM


MVVM可以說是MV(X)系列中最新興起的也是最出色的一種架構(gòu),,而它也廣受我們iOS程序員喜愛,。

MVVM


MVVM和MVP很像:

  • 把ViewController看成View

  • View和Model之間沒有緊耦合


另外它還讓VIew和ViewModel做了數(shù)據(jù)綁定。ViewModel可以調(diào)用對Model做更改,,也可以再Model更新的時候?qū)ψ陨磉M行調(diào)整,,然后通過View和ViewModel之間的綁定,對View進行相應的更新,。

關(guān)于綁定


在iOS平臺上面有KVO和通知,,但是用起來總是覺得不太方便,所以有一些三方庫供我們選擇:

  • 基于KVO的綁定庫,,如 RZDataBinding 或者 SwiftBond

  • 使用全量級的 函數(shù)式響應編程 框架,比如ReactiveCocoaRxSwift 或者PromiseKit


實際上,,我們在提到MVVM的時候就很容易想到ReactiveCocoa,它也是我們在iOS中使用MVVM的最好工具,。但是相對來說它的學習成本和維護成本 也是比較高的,,而且一旦你應用不當,很可能造成災難性的問題,。

下面我暫時不用RAC來簡單展示一下MVVM:

MVVM


界面很簡單,,就是點擊一個button修改label里面的數(shù)據(jù)

界面


Model

@interface MVVMModel : NSObject
@property (nonatomic, copy) NSString *text;
@end
@implementation MVVMModel
- (NSString *)text{
   _text = [NSString stringWithFormat:@'newText%d',rand()];
   return _text;
}


ViewModel

@interface MVVMViewModel : NSObject
- (void)changeText;
@end
@interface MVVMViewModel()
@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) MVVMModel *model;
@end
@implementation MVVMViewModel
- (instancetype)init
{
   self = [super init];
   if (self) {
       self.model = [MVVMModel new];
   }
   return self;
}
- (void)changeText{
   self.text = self.model.text;;
}


Controller

@interface MVVMViewController ()
@property (weak, nonatomic) IBOutlet UILabel *textLabel;
@property (nonatomic, strong) MVVMViewModel *viewModel;
@end
@implementation MVVMViewController
- (void)viewDidLoad {
   [super viewDidLoad];
   self.viewModel = [[MVVMViewModel alloc]init];
   [self.viewModel addObserver:self forKeyPath:@'text' options:NSKeyValueObservingOptionNew context:nil];
}
- (IBAction)buttonClicked:(UIButton *)sender {
   [self.viewModel changeText];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
   self.textLabel.text = change[@'new'];
}


MVVM的核心就是View和ViewModel的一個綁定,這里我只是簡單的通過KVO實現(xiàn),,看起來并不是那么優(yōu)雅,,想要深度使用的話我覺得還是有必要學習一下RAC的,完整的Demo(https://github.com/RhettTamp/MVXDemo)

下面我們再來對MVVM的各方面表現(xiàn)做一個評價:

  • 劃分——MVVM 框架里面的 View 比 MVP 里面負責的事情要更多一些,。因為前者是通過 ViewModel 的數(shù)據(jù)綁定來更新自身狀態(tài)的,,而后者只是把所有的事件統(tǒng)統(tǒng)交給 Presenter 去處理就完了,自己本身并不負責更新,。

  • 可測性—— 因為 ViewModel 對 View 是一無所知的,,這樣我們對它的測試就變得很簡單。View 應該也是能夠被測試的,,但是可能因為它對 UIKit 的依賴,,你會直接略過它。

  • 易用——它比MVP會更加簡潔,,因為在 MVP 下你必須要把 View 的所有事件都交給 Presenter 去處理,,而且需要手動的去更新 View 的狀態(tài);而在 MVVM 下,,你只需要用綁定就可以解決,。


綜上:MVVM 真的很有魅力,,因為它不僅結(jié)合了上述幾種框架的優(yōu)點,還不需要你為視圖的更新去寫額外的代碼(因為在 View 上已經(jīng)做了數(shù)據(jù)綁定),,另外它在可測性上的表現(xiàn)也依然很棒,。

為了簡單易懂,以上的Demo都非常簡潔,,不知道看了這篇博客能否加深你對MV(X)的一些理解,,這些理解也僅作為我個人的一些參考,有什么不對的地方希望大家指出,。




  • 作者:Tamp

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多