iOS-设计模式(MVC、MVP、MVVM)

App开发过程中,随着业务的不断发展,代码和逻辑不断增加,有时候不得不重构以前的代码,好的架构,决定了代码的易用性、可扩展性、可维护性、可读性以及健壮性等等,利于代码的拓展和重构,下面就简单探讨一下iOS中常见的设计模式吧。
本文中主要介绍三种设计模式MVCMVPMVVM

一、MVC模式

Models: 数据层,负责数据的处理和获取的数据接口层。
Views:展示层,即UI层(实际开发中也是业务模型)。
Controller: 控制器层,它是 Model 和 View 之间的桥梁。当用户对 View 有操作时它负责去修改相应 Model;当 Model 的值发生变化时它负责去更新对应 View。

MVC.jpg

优点: 对Controller进行瘦身,将View内部的细节封装起来。
缺点: View依赖于Model,没有区分业务逻辑和业务展示

MVC核心代码:

// 1.controller类

@implementation MVCViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建view
     MVCHeaderView *headView = [[MVCHeaderView alloc] init];
     headView.frame = CGRectMake(100, 100, 100, 150);
     headView.mvcDelegate = self;
     [self.view addSubview:headView];
     
     // 加载模型数据
     MVCModel *model = [[MVCModel alloc] init];
     model.name = @"翀鹰精灵";
     model.image = @"header";
     
     // 设置数据到view上
     headView.mvcModel = model;
}
#pragma mark - MJAppViewDelegate
- (void)viewDidClick:(MVCHeaderView *)headView {
    NSLog(@"控制器监听到了appView的点击");
}

@end



// 2.view类

//2.1  MVCHeaderView.h
@class MVCHeaderView,MVCModel;
@protocol MVCViewDelegate <NSObject>
@optional
-(void)viewDidClick:(MVCHeaderView*)headView;
@end

@interface MVCHeaderView : UIView
@property (nonatomic, strong) MVCModel  * mvcModel;
@property (nonatomic, weak) id<MVCViewDelegate> mvcDelegate;
@end

//2.2  MVCHeaderView.m
@interface MVCHeaderView()
@property (weak, nonatomic) UIImageView *iconView;
@property (weak, nonatomic) UILabel *nameLabel;
@end

@implementation MVCHeaderView
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        UIImageView *iconView = [[UIImageView alloc] init];
        iconView.frame = CGRectMake(0, 0, 100, 100);
        [self addSubview:iconView];
        _iconView = iconView;
        
        UILabel *nameLabel = [[UILabel alloc] init];
        nameLabel.frame = CGRectMake(0, 100, 100, 30);
        nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:nameLabel];
        _nameLabel = nameLabel;
    }
    return self;
}

- (void)setMvcModel:(MVCModel *)mvcModel {
    _mvcModel = mvcModel;
    self.iconView.image = [UIImage imageNamed:mvcModel.image];
    self.nameLabel.text = mvcModel.name;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if ([self.mvcDelegate respondsToSelector:@selector(viewDidClick:)]) {
        [self.mvcDelegate viewDidClick:self];
    }
}
@end

// 3.model类

@interface MVCModel : NSObject
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *image;
@end
二、MVP模式

MVP 架构模式是 MVC 的一个变种,MVC 与 MVP 之间的区别其实并不明显,作者认为两者之间最大的区别就是 MVP 中使用 Presenter 对视图和模型进行了解耦,它们彼此都对对方一无所知,沟通都通过 Presenter 进行。

MVP 中,Presenter 可以理解为松散的控制器,其中包含了视图的 UI 业务逻辑。

MVP.JPG

MVP核心代码:
// 1.controller类

#import "MVPViewController.h"
#import "MVPHeaderPresenter.h"

@interface MVPViewController ()
@property (strong, nonatomic) MVPHeaderPresenter *presenter;
@end

@implementation MVPViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.presenter = [[MVPHeaderPresenter alloc] initWithController:self];
}

@end

// 2.view类 复用MVC中view类
// 3.Presenter类

//3.1 MVPHeaderPresenter.h
#import <UIKit/UIKit.h>

@interface MVPHeaderPresenter : NSObject
- (instancetype)initWithController:(UIViewController *)controller;

@end
//3.2 MVPHeaderPresenter.m
#import "MVPHeaderPresenter.h"
#import "MVPHeaderView.h"
#import "MVPModel.h"

@interface MVPHeaderPresenter() <MVPViewDelegate>
@property (weak, nonatomic) UIViewController *controller;
@end


@implementation MVPHeaderPresenter
- (instancetype)initWithController:(UIViewController *)controller {
     if (self = [super init]) {
            self.controller = controller;
            
            // 创建View
            MVPHeaderView *headView = [[MVPHeaderView alloc] init];
            headView.frame = CGRectMake(100, 100, 100, 150);
            headView.mvpDelegate = self;
            [controller.view addSubview:headView];
            
            // 加载模型数据
            MVPModel *model = [[MVPModel alloc] init];
            model.name = @"【MVP】翀鹰精灵";
            model.image = @"header";
            
            // 赋值数据
            [headView setName:model.name andImage:model.image];
        }
        return self;
}

@end

三、MVVM模式

MVVM由三个部分组成,也就是 Model、View 和 ViewModel;其中视图模型(ViewModel)和View进行了一个双向绑定.

MVVM.JPG

MVVM核心代码:
// 1.controller类

#import "MVVMViewController.h"
#import "MVVMViewModel.h"

@interface MVVMViewController ()
@property (strong, nonatomic) MVVMViewModel *viewModel;

@end

@implementation MVVMViewController

- (void)viewDidLoad {
    [super viewDidLoad];
     self.viewModel = [[MVVMViewModel alloc] initWithController:self];
}

@end

// 2.view类


- (void)setMvvmModel:(MVVMViewModel *)mvvmModel {
    _mvvmModel = mvvmModel;
    
    __weak typeof(self) waekSelf = self;
    [self.KVOController observe:mvvmModel keyPath:@"name" options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
        waekSelf.nameLabel.text = change[NSKeyValueChangeNewKey];
    }];
    
    [self.KVOController observe:mvvmModel keyPath:@"image" options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSKeyValueChangeKey,id> * _Nonnull change) {
        waekSelf.iconView.image = [UIImage imageNamed:change[NSKeyValueChangeNewKey]];
    }];
}

// 3.viewModel类

@implementation MVVMViewModel

- (instancetype)initWithController:(UIViewController *)controller {
    if (self = [super init]) {
        self.controller = controller;
        
        // 创建View
        MVVMHeaderView *headView = [[MVVMHeaderView alloc] init];
        headView.frame = CGRectMake(100, 100, 200, 150);
        headView.mvvmModel = self;
        headView.mvvmDelegate = self;
        [controller.view addSubview:headView];
        
        // 加载模型数据
        MVVMModel *model = [[MVVMModel alloc] init];
        model.name = @"【MVVM】翀鹰精灵";
        model.image = @"header";
        self.name = model.name;
        self.image = model.image;
    }
    return self;
}

#pragma mark - MJAppViewDelegate
- (void)mvvmViewDidClick:(MVVMHeaderView *)appView {
    NSLog(@"viewModel 监听了 appView 的点击");
    self.name = @"变化中的【mvvm】";
    self.image =  @"header";
}

@end

最后,没有最好的,适合项目的才是最好的架构。
Demo下载.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358