iOS架构模式MVC、MVP、MVVM(内附demo)

来源:互联网 发布:windows 许可证过期 编辑:程序博客网 时间:2024/06/01 10:30

MVC

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

MVC结构如图所示:
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结构如图:
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

#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结构如图:
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

原创粉丝点击