iOS进阶之架构设计MVC、MVP、MVVM(12)

转载自:iOS架构模式MVC、MVP、MVVM(内附demo)
文章对比了MVC、MVP、MVVM,结构清晰,示例简单,容易让人接受。所以转载至此。以供自己赏读。

MVC

MVC的实现思路是:用户操作View,在Controller层完成业务逻辑处理,更新Model层,将数据显示在View层。
在MVC中,每个层之间都有关联,耦合比较紧,在大型项目中,维护起来比较费力。
View把控制权交给Controller层,自己不执行业务逻辑;Controller层执行业务逻辑并且操作Model层,但不会直接操作View层;View和Model层的同步消息是通过观察者模式进行,而同步操作是由View层自己请求Model层的数据,然后对视图进行更新,观察者模式可以做到多视图同时更新。

MVC结构如图所示:

在这里插入图片描述
模型层:
Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;

@end

Person.m

#import "Person.h"

@implementation Person

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
    self = [super init];
    if (self) {
        _firstName = firstName;
        _lastName = lastName;
    }
    return self;
}

@end

视图层:
TestView.h

#import <UIKit/UIKit.h>

@interface TestView : UIView

@property (nonatomic, strong) UILabel *nameLabel;

@end

TestView.m

#import "TestView.h"

@implementation TestView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
        self.nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.nameLabel];
    }
    return self;
}

@end

控制器层:
ViewController.m

#import "ViewController.h"
#import "Person.h"
#import "TestView.h"

@interface ViewController ()

@property (nonatomic, strong) Person *personModel;
@property (nonatomic, strong) TestView *testView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupViews];

    if (self.personModel.firstName.length > 0) {
        self.testView.nameLabel.text = self.personModel.firstName;
    } else {
        self.testView.nameLabel.text = self.personModel.lastName;
    }

}

- (void)setupViews {
    self.personModel = [[Person alloc] initWithFirstName:@"" lastName:@"胡歌"];
    self.testView = [[TestView alloc] initWithFrame:CGRectMake(100, 100, CGRectGetWidth(self.view.bounds)-200, 50)];
    [self.view addSubview:self.testView];
}

@end

MVP

**MVP的实现思路是:**用户操作View,在Presenter层完成业务逻辑处理,更新Model层,通过Presenter将数据显示在View层,完全隔断Model和View之间的通信。
我们通过接口的方式来连接view和presenter层,这样导致的问题是,如果页面过于复杂,我们的接口就会很多,为了更好的处理类似的问题,需要定义一些基类接口,把一些公共的逻辑,比如网络请求,toast,提示框等放在里面。
因为MVP不依赖Model,所以可以更好的进行组件化,把它从特定的场景中脱离出来,做到高度复用。MVP中的Presenter更多的作为框架的控制者,承担了大量的逻辑操作。

MVP结构如图:

在这里插入图片描述
模型层:
Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;

@end

Person.m

#import "Person.h"

@implementation Person

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
    self = [super init];
    if (self) {
        _firstName = firstName;
        _lastName = lastName;
    }
    return self;
}

@end

视图层:
TestView.h

扫描二维码关注公众号,回复: 8726925 查看本文章
#import <UIKit/UIKit.h>

@interface TestView : UIView

@property (nonatomic, strong) UILabel *nameLabel;

@end

TestView.m

#import "TestView.h"

@implementation TestView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
        self.nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.nameLabel];
    }
    return self;
}

@end

Presenter层:
PersonViewProtocol.h

#import <Foundation/Foundation.h>

@protocol PersonViewProtocol <NSObject>

- (void)setNameText:(NSString *)nameText;

@end

Presenter.h

#import <Foundation/Foundation.h>
#import "PersonViewProtocol.h"

@interface Presenter : NSObject

- (void)attachView:(id <PersonViewProtocol>)view;

- (void)fetchData;

@end

Presenter.m

#import "Presenter.h"
#import "Person.h"

@interface Presenter()

@property (nonatomic, strong) Person *person;
@property (nonatomic, weak) id<PersonViewProtocol> attachView;

@end

@implementation Presenter

- (void)attachView:(id<PersonViewProtocol>)view {
    self.attachView = view;
}

- (void)fetchData {
    self.person = [[Person alloc] initWithFirstName:@"赵丽颖" lastName:@"胡歌"];
    if (self.person.firstName.length > 0) {
        [self.attachView setNameText:self.person.firstName];
    } else {
        [self.attachView setNameText:self.person.lastName];
    }
}

@end

ViewController.m

#import "ViewController.h"
#import "PersonViewProtocol.h"
#import "Presenter.h"
#import "TestView.h"

@interface ViewController ()<PersonViewProtocol>

@property (nonatomic, strong) TestView *testView;
@property (nonatomic, strong) Presenter *presenter;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupViews];

    self.presenter = [Presenter new];
    [self.presenter attachView:self];
    [self.presenter fetchData];
}

- (void)setupViews {
    self.testView = [[TestView alloc] initWithFrame:CGRectMake(100, 100, CGRectGetWidth(self.view.bounds)-200, 50)];
    [self.view addSubview:self.testView];

}

#pragma PersonViewProtocol
- (void)setNameText:(NSString *)nameText {
    self.testView.nameLabel.text = nameText;
}

@end

MVVM

MVVM和MVP的最大区别是采用了双向绑定机制,View的变动,自动反映在ViewModel上。
MVVM结构如图:

在这里插入图片描述
模型层:
Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;

@end

Person.m

#import "Person.h"

@implementation Person

- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
    self = [super init];
    if (self) {
        _firstName = firstName;
        _lastName = lastName;
    }
    return self;
}

@end

视图层:
TestView.h

#import <UIKit/UIKit.h>

@interface TestView : UIView

@property (nonatomic, strong) UILabel *nameLabel;

@end

TestView.m

#import "TestView.h"

@implementation TestView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
        self.nameLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:self.nameLabel];
    }
    return self;
}

@end

ViewModel层:
PersonViewModel.h

#import <Foundation/Foundation.h>
#import "Person.h"

@interface PersonViewModel : NSObject

@property (nonatomic, readonly) Person *person;
@property (nonatomic, readonly) NSString *nameText;

- (instancetype)initWithPerson:(Person *)person;

@end

PersonViewModel.m

#import "PersonViewModel.h"

@implementation PersonViewModel

- (instancetype)initWithPerson:(Person *)person {
    self = [super init];
    if (self) {
        _person = person;
        if (_person.firstName.length > 0) {
            _nameText = _person.firstName;
        } else {
            _nameText = _person.lastName;
        }
    }
    return self;
}

@end

ViewController.m

#import "ViewController.h"
#import "PersonViewModel.h"
#import "TestView.h"

@interface ViewController ()

@property (nonatomic, strong) TestView *testView;
@property (nonatomic, strong) PersonViewModel *viewModel;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setupViews];

    self.testView.nameLabel.text = self.viewModel.nameText;

}

- (void)setupViews {
    Person *person = [[Person alloc] initWithFirstName:@"" lastName:@"胡歌"];
    self.viewModel = [[PersonViewModel alloc] initWithPerson:person];
    self.testView = [[TestView alloc] initWithFrame:CGRectMake(100, 100, CGRectGetWidth(self.view.bounds)-200, 50)];
    [self.view addSubview:self.testView];
}

@end

(MVC、MVP、MVVM)Demo下载)
密码:pmv6

发布了249 篇原创文章 · 获赞 224 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/shifang07/article/details/100746503