MVC/MVP/MVVM 三种设计模式简介附demo

前言:说到设计模式,许多人认为是很高深的东西,其实许多都是由简单演变而来,或许MVC模式并不难理解因为熟悉,其他模式其实也是同样如此。MVC ->MVP ->MVVM 每次演变都是为了低耦合,易维护的目的,但也不是一成不变,多种混合也是可以同时存在, 所以我们需要抓住每个理念的核心概念,选择合适的方式应用到工程中理解会更深!

参考文献:https://blog.nodejitsu.com/scaling-isomorphic-javascript-code/

一、MVC

《MVC/MVP/MVVM 三种设计模式简介附demo》 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 三种设计模式简介附demo》 ** 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()%10);

}

三、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(150,100 , 100, 30)];
        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(150, 200, 50, 50);
        [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

    原文作者:_方丈
    原文地址: https://www.jianshu.com/p/545f2b94ee3d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞