MVC
MVC架構(gòu)模式: Model-View-Controller是一個(gè)用來(lái)組織代碼的權(quán)威范式。Apple甚至是這么說(shuō)的。在MVC下,所有的對(duì)象被歸類為一個(gè)model,一個(gè)view,或一個(gè)controller。Model持有數(shù)據(jù),View顯示與用戶交互的界面,而View Controller調(diào)解Model和View之間的交互。
用戶操作View, 在Controller層完成業(yè)務(wù)邏輯處理, 更新Model層, 將數(shù)據(jù)顯示在View層.
- Model層
@interface Person : NSObject
@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;
@end
@implementation Person
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
if ([super init]) {
_firstName = firstName;
_lastName = lastName;
}
return self;
}
@end
- View層
@interface TestView : UIView
@property (nonatomic, strong) UILabel *nameLabel;
@end
@implementation TestView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
_nameLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_nameLabel];
}
return self;
}
@end
- Controller層
@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:@"XXX"];
self.testView = [[TestView alloc] initWithFrame:CGRectMake(100, 100, CGRectGetWidth(self.view.bounds)-200, 50)];
[self.view addSubview:self.testView];
}
@end
MVP
MVP架構(gòu)模式: Model-View-Presenter是MVC的改良模式,由IBM的子公司Taligent提出。和MVC的相同之處在于:Controller/Presenter負(fù)責(zé)業(yè)務(wù)邏輯,Model管理數(shù)據(jù),View負(fù)責(zé)顯示只不過(guò)是將 Controller 改名為 Presenter,同時(shí)改變了通信方向。
View 與 Model 不通信,都通過(guò) Presenter 傳遞。Presenter完全把Model和View進(jìn)行了分離,主要的程序邏輯在Presenter里實(shí)現(xiàn)。
- Model層
@interface Person : NSObject
@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;
@end
@implementation Person
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
if (self = [super init]) {
_firstName = firstName;
_lastName = lastName;
}
return self;
}
@end
- View層
@interface TestView : UIView
@property (nonatomic, strong) UILabel *nameLabel;
@end
@implementation TestView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
_nameLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_nameLabel];
}
return self;
}
@end
- Presenter層
@protocol PersonViewProtocol
- (void)setNameText:(NSString *)nameText;
@end
@interface Presenter : NSObject
- (void)attachView:(id )view;
- (void)fetchData;
@end
@interface Presenter()
@property (nonatomic, strong) Person *person;
@property (nonatomic, weak) id attachView;
@end
@implementation Presenter
- (void)attachView:(id)view {
self.attachView = view;
}
- (void)fetchData {
self.person = [[Person alloc] initWithFirstName:@"AAA" lastName:@"BB"];
if (self.person.firstName.length > 0) {
[self.attachView setNameText:self.person.firstName];
} else {
[self.attachView setNameText:self.person.lastName];
}
}
@end
- Controller
@interface ViewController ()
@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架構(gòu)模式: Model-View-ViewModel是 M-V-VM 三部分組成,它本質(zhì)上就是 MVC 的改進(jìn)版. 在 MVC 下,所有的對(duì)象被歸類為一個(gè) model,一個(gè) view,或一個(gè) controller。Model 持有數(shù)據(jù),View 顯示與用戶交互的界面,而 View Controller 調(diào)解 Model 和 View 之間的交互。然而,隨著模塊的迭代我們?cè)絹?lái)越發(fā)現(xiàn) MVC 自身存在著很多不足。因此,MVVM 從其他應(yīng)用而出,在 iOS 中從此我們完全將業(yè)務(wù)邏輯加以區(qū)分并使用這套思想。在 MVVM 中他的設(shè)計(jì)思路和 MVC 很像。它正式規(guī)范了視圖和控制器緊耦合的性質(zhì),并引入新的組件 ViewModel。此外,它還有像監(jiān)管版本的 MVP 那樣的綁定功能,但這個(gè)綁定不是在 View 和 Model 之間而是在 View 和 ViewModel 之間。
- Model層
@interface Person : NSObject
@property (nonatomic, readonly) NSString *firstName;
@property (nonatomic, readonly) NSString *lastName;
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;
@end
@implementation Person
- (instancetype)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName {
if (self = [super init]) {
_firstName = firstName;
_lastName = lastName;
}
return self;
}
@end
- View層
@interface TestView : UIView
@property (nonatomic, strong) UILabel *nameLabel;
@end
@implementation TestView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_nameLabel = [[UILabel alloc] initWithFrame:self.bounds];
_nameLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_nameLabel];
}
return self;
}
@end
- ViewModel層
@interface PersonViewModel : NSObject
@property (nonatomic, readonly) Person *person;
@property (nonatomic, readonly) NSString *nameText;
- (instancetype)initWithPerson:(Person *)person;
@end
@implementation PersonViewModel
- (instancetype)initWithPerson:(Person *)person {
if (self = [super init]) {
_person = person;
if (_person.firstName.length > 0) {
_nameText = _person.firstName;
} else {
_nameText = _person.lastName;
}
}
return self;
}
@end
- Controller
@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:@"AAA" lastName:@"BB"];
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