天天看點

MVC/MVP/MVVM 三種設計模式 彙總

原文 :http://blog.csdn.net/hudan2714/article/details/50990359

MVC

MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、資料、界面顯示分離的方法組織代碼,将業務邏輯聚集到一個部件裡面,在改進和個性化定制界面及使用者互動的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用于映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化使用者界面的結構中。
MVC/MVP/MVVM 三種設計模式 彙總

資料關系

  • View 接受使用者互動請求
  • View 将請求轉交給Controller
  • Controller 操作Model進行資料更新
  • 資料更新之後,Model通知View更新資料變化
  • View 更新變化資料

方式

所有方式都是單向通信

結構實作

View :使用 Composite模式 

View和Controller:使用 Strategy模式 

Model和 View:使用 Observer模式同步資訊

使用

MVC中的View是可以直接通路Model的!進而,View裡會包含Model資訊,不可避免的還要包括一些業務邏輯。在MVC模型裡,更關注的Model的不變,而同時有多個對Model的不同顯示,及View。是以,在MVC模型裡,Model不依賴于View,但是 View是依賴于Model的。不僅如此,因為有一些業務邏輯在View裡實作了,導緻要更改View也是比較困難的,至少那些業務邏輯是無法重用的。

MVP

mvp的全稱為Model-View-Presenter,Model提供資料,View負責顯示,Controller/Presenter負責邏輯的處理。MVP與MVC有着一個重大的差別:在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,所有的互動都發生在Presenter内部,而在MVC中View會直接從Model中讀取資料而不是通過 Controller。
MVC/MVP/MVVM 三種設計模式 彙總

資料關系

  • View 接收使用者互動請求
  • View 将請求轉交給 Presenter
  • Presenter 操作Model進行資料更新
  • Model 通知Presenter資料發生變化
  • Presenter 更新View資料

MVP的優勢

  1. Model與View完全分離,修改互不影響
  2. 更高效地使用,因為所有的邏輯互動都發生在一個地方—Presenter内部
  3. 一個Preseter可用于多個View,而不需要改變Presenter的邏輯(因為View的變化總是比Model的變化頻繁)。
  4. 更便于測試。把邏輯放在Presenter中,就可以脫離使用者接口來測試邏輯(單元測試)

方式

各部分之間都是雙向通信

結構實作

View :使用 Composite模式 

View和Presenter:使用 Mediator模式 

Model和Presenter:使用 Command模式同步資訊

MVC和MVP差別

MVP與MVC最大的一個差別就是:Model與View層之間倒底該不該通信(甚至雙向通信)

MVC和MVP關系

MVP:是MVC模式的變種。
項目開發中,UI是容易變化的,且是多樣的,一樣的資料會有N種顯示方式;業務邏輯也是比較容易變化的。為了使得應用具有較大的彈性,我們期望将UI、邏輯(UI的邏輯和業務邏輯)和資料隔離開來,而MVP是一個很好的選擇。
Presenter代替了Controller,它比Controller擔當更多的任務,也更加複雜。Presenter處理事件,執行相應的邏輯,這些邏輯映射到Model操作Model。那些處理UI如何工作的代碼基本上都位于Presenter。
MVC中的Model和View使用Observer模式進行溝通;MPV中的Presenter和View則使用Mediator模式進行通信;Presenter操作Model則使用Command模式來進行。基本設計和MVC相同:Model存儲資料,View對Model的表現,Presenter協調兩者之間的通信。在 MVP 中 View 接收到事件,然後會将它們傳遞到 Presenter, 如何具體處理這些事件,将由Presenter來完成。
如果要實作的UI比較複雜,而且相關的顯示邏輯還跟Model有關系,就可以在View和 Presenter之間放置一個Adapter。由這個 Adapter來通路Model和View,避免兩者之間的關聯。而同時,因為Adapter實作了View的接口,進而可以保證與Presenter之 間接口的不變。這樣就可以保證View和Presenter之間接口的簡潔,又不失去UI的靈活性。
           

使用

MVP的實作會根據View的實作而有一些不同,一部分傾向于在View中放置簡單的邏輯,在Presenter放置複雜的邏輯;另一部分傾向于在presenter中放置全部的邏輯。這兩種分别被稱為:Passive View和Superivising Controller。

MVVM

MVVM是Model-View-ViewModel的簡寫。微軟的WPF帶來了新的技術體驗,如Silverlight、音頻、視訊、3D、動畫……,這導緻了軟體UI層更加細節化、可定制化。同時,在技術層面,WPF也帶來了 諸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View-ViewModel)架構的由來便是MVP(Model-View-Presenter)模式與WPF結合的應用方式時發展演變過來的一種新型架構架構。它立足于原有MVP架構并且把WPF的新特性糅合進去,以應對客戶日益複雜的需求變化。
MVC/MVP/MVVM 三種設計模式 彙總

資料關系

  • View 接收使用者互動請求
  • View 将請求轉交給ViewModel
  • ViewModel 操作Model資料更新
  • Model 更新完資料,通知ViewModel資料發生變化
  • ViewModel 更新View資料

方式

雙向綁定。View/Model的變動,自動反映在 ViewModel,反之亦然。

使用

  • 可以相容你當下使用的 MVC/MVP 架構。
  • 增加你的應用的可測試性。
  • 配合一個綁定機制效果最好。

MVVM優點

MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model),有幾大優點: 

1. 低耦合。View可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的”View”上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。 

2. 可重用性。你可以把一些視圖邏輯放在一個ViewModel裡面,讓很多view重用這段視圖邏輯。 

3. 獨立開發。開發人員可以專注于業務邏輯和資料的開發(ViewModel),設計人員可以專注于頁面設計,生成xml代碼。 

4. 可測試。界面素來是比較難于測試的,而現在測試可以針對ViewModel來寫。

mvc,mvp,mvvm三者演化

MVC/MVP/MVVM 三種設計模式 彙總

說明

任何的項目架構,都是為項目服務的。沒有絕對的好壞之分,隻有更合适的選擇。在項目進展的不同階段,做出最合适的調整,才是是更适合團隊項目發展的架構。項目設計者要謹記,任何的項目設計,都是要圍繞項目發展階段,團隊成員規模,和團隊整體能力而定的。切莫為了設計而設計,為了架構而架構。快速,高效的配合整個團隊進展項目,才是最合适的架構。才是一個程式員為成一個leader,成為一個架構師的必經之路。

轉載,請說明來源:http://blog.csdn.net/hudan2714/article/details/50990359

參考文獻:https://blog.nodejitsu.com/scaling-isomorphic-javascript-code/

一、MVC

MVC/MVP/MVVM 三種設計模式 彙總

MVC

由螢幕擷取響應指令, View 傳送指令到 Controller,Controller 完成業務邏輯後,要求Model 改變狀态Model 将新的資料發送到 View,使用者得到回報

MVCViewController.m

#import "MVCViewController.h"
#import "MVCView.h"
#import "MVCModel.h"
@interface MVCViewController ()<MVCDelegate>

@end
@implementation MVCViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    MVCView *view = [[MVCView alloc]initWithFrame:[UIScreen mainScreen].bounds];
    view.delegate = self;

    MVCModel *model = [MVCModel new];

    model.name = @"name1";

    [view setViewWithModel:model];

}
#pragma mark - delegate
//代理來傳回view對viewController的操控
-(void)clickChange{

    NSLog(@"chang  from View!");
}
           

二、 MVP

MVP 模式将 Controller 改換為 Presenter,同時斷開View和Model之間聯系,通過Presenter做橋梁來溝通。

MVC/MVP/MVVM 三種設計模式 彙總

MVP

  1. 各部分之間的通信,都是雙向的。
  2. View 與 Model 不發生聯系,都通過 Presenter 傳遞。
  3. View 非常薄,不部署任何業務邏輯,稱為"被動視圖"(Passive View),即沒有任何主動性,而 Presenter非常厚,所有邏輯都部署在那裡。
  4. Presenter 可以另一種了解為View和Model的管家

MVPViewController.m

#import "MVPViewController.h"
#import "MVPPresenter.h"
#import "MVPCell.h"
#import "MVPModel.h"

@implementation MVPViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];

    MVPPresenter *present = [MVPPresenter new];
    MVPCell *view = [MVPCell new];
    MVPModel *model = [MVPModel new];

    //擷取資料
    model.name = @"name1";

    //視圖布局
    [self.view addSubview:view];

    //交給presenter處理 ,避免 view和 model 之間的互動
    [present setPreModel:model];
    [present setPreView:view];
}
           

MVPPresenter .h /.m

#import <Foundation/Foundation.h>
#import "MVPModel.h"
#import "MVPCell.h"
@interface MVPPresenter : NSObject 
@property(nonatomic,strong)MVPCell *MVPView;
@property(nonatomic,strong)MVPModel *model;

-(void)setPreView:(MVPCell *)view;
-(void)setPreModel:(MVPModel *)model;

-(void)clickChangName;
           
#import "MVPPresenter.h"
@implementation MVPPresenter
- (instancetype)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

-(void)setPreModel:(MVPModel *)model{
    self.model = model;
}

-(void)setPreView:(MVPCell *)view{
    self.MVPView = view;
    [self.MVPView setlabel:_model.name];
}

-(void)clickChangName{

    NSLog(@"name change %d",arc4random()%);

}
           

三、MVVM

MVVM 模式将 Presenter 改名為 ViewModel,基本上與 MVP 模式完全一緻。

唯一的差別是,它采用雙向綁定(data-binding):View <->ViewModel , ViewModel作為Model中值得的映射,是資料發生改變時,通知View中發生改變 ,以後不需要考慮View和Model 之間的互動更新,隻需着手界面布局邏輯即可

MVVMViewController.m

#import "MVVMViewController.h"
#import "MVVMView.h"
#import "MVVMModel.h"
#import "MVVMViewModel.h"
@interface MVVMViewController ()

@end

@implementation MVVMViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    MVVMView *MView = [MVVMView new];

    MVVMModel *model = [MVVMModel new];
    model.name = @"name1";
    MVVMViewModel *viewModel = [MVVMViewModel new];

    [self.view addSubview:MView];

    //* viewModel 作為樞紐 溝通view和model之間關系
    [viewModel setWithModel:model];
    [MView setWithViewMoel:viewModel];
}
           

關鍵點:

  1. 将viewModel 中

    nameStr

    與Model 中

    name

    相對應;
  2. View中

    label

    的text值将與

    nameStr

    進行綁定(KVO鍵值觀察)
  3. 這樣model的值發生改變時 ,View會自動發生改變
  4. View 和Model通過ViewModel實作動态關聯

MVVMModel

#import <Foundation/Foundation.h>

@interface MVVMModel : NSObject
@property(nonatomic,copy)NSString *name;

@end
           

MVVMViewModel.h

#import "MVVMModel.h"
@interface MVVMViewModel : NSObject
//對應Model中name
@property(nonatomic,copy)NSString *nameStr;

@property(nonatomic,strong)MVVMModel *model;

-(void)setWithModel:(MVVMModel *)model;
-(void)clickChangeName;
           

MVVMView.m 利用KVO監測值變化

#import "MVVMView.h"
#import "NSObject+FBKVOController.h"
@interface MVVMView ()

@property(nonatomic,strong)MVVMViewModel *vm;
@property(nonatomic,strong)UILabel *label;
@property(nonatomic,strong)UIButton *button;

@end
@implementation MVVMView
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        self.frame = [UIScreen mainScreen].bounds;

        self.label = [[UILabel alloc]initWithFrame:CGRectMake(, , , )];
        self.label.backgroundColor = [UIColor orangeColor];
        [self addSubview:_label];

        self.button = [UIButton new];
        _button.backgroundColor = [UIColor redColor];
        [_button setTitle:@"點選" forState:UIControlStateNormal];
        [_button addTarget:self action:@selector(mvvmClickChangModel) forControlEvents:UIControlEventTouchUpInside];
        _button.frame = CGRectMake(, , , );
        [self addSubview:_button];
    }
    return self;
}
-(void)setWithViewMoel:(MVVMViewModel *)vm{
    self.vm = vm;
    //KVO
    [self.vm addObserver:self forKeyPath:@"nameStr" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
    self.label.text = vm.nameStr;

//    //* FBKVO 第三方庫
//    [self.KVOController observe:self.vm keyPath:@"nameStr" options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSString *,id> * _Nonnull change) {
//        self.label.text = change[NSKeyValueChangeNewKey];
//    }];

}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    if ([keyPath isEqualToString:@"nameStr"]&&[change objectForKey:NSKeyValueChangeNewKey]) {
        NSNumber *new = [change objectForKey:NSKeyValueChangeNewKey];
        self.label.text = [NSString stringWithFormat:@"%@",new];
    }
}
-(void)mvvmClickChangModel{
    [self.vm clickChangeName];
}
-(void)dealloc{
    [self.vm removeObserver:self forKeyPath:@"nameStr"];
}
           

Example Demo

GitHub : https://github.com/one-tea/MVC-MVP-MVVM.git

3

繼續閱讀