MVC与MVVM设计模式理解
MVC设计模式
MVC是一种架构模式,M表示Model,V表示视图View,C表示控制器Controller:
- Model负责存储、定义、操作数据;
- View用来展示给用户,并且和用户进行交互;
- Controller是Model和View的协调者,Controller把Model中的数据拿过来给View使用。Controller可以直接与Model和View进行通信,而View不能与Controller直接通信。,当有数据更新时,Model也要与Controller进行通信,这个时候就要用Notification和KVO,这个方式就像发广播一样,Model发信号,Controller设置接收监听信号,当有数据更新是就发信号给Controller,Model和View不能直接通信,这样违背MVC设计原则。View与Controller通信需要利用代理协议的方式,Controller可以直接根据Model决定View的展示。View如果接受响应事件则通过delegate,target-action,block等方式告诉Controller的状态变化。Controller进行业务的处理,然后再控制View的展示。
那这样Model和View就是相互独立的。View只负责页面的展示,Model只是数据的存储,那么也就达到了解耦和重用的目的。
实例:假设苹果根据买iPhone的人给予不同的优惠,学生优惠20%,it民工优惠50%,其他不优惠。
//客户类
typedef NS_ENUM(NSInteger, CustomerType) {
CustomerTypeStudent,
CustomerTypeiT,
CustomerTypeOther,
};
@interface Customer : NSObject
@property (nonatomic, assign) CustomerType customerType;
@end
//iPhone类
@interface iPhone : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *price;
@end
//VC类
@interface ViewController ()
@property (nonatomic, strong) iPhone *iphone;
@property (nonatomic, strong) Customer *customer;
@property (weak, nonatomic) IBOutlet UILabel *lblName;
@property (weak, nonatomic) IBOutlet UILabel *lblPrice;
@property (weak, nonatomic) IBOutlet UILabel *lblDiscount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"手机优惠";
self.lblName.text = self.iphone.name;
self.lblPrice.text = self.iphone.price;
if (self.customer.customerType == CustomerTypeStudent) {
self.lblDiscount.text = @"优惠20%";
}
else if (self.customer.customerType == CustomerTypeiT) {
self.lblDiscount.text = @"优惠50%";
}
else {
self.lblDiscount.text = @"没有优惠";
}
}
@end
MVVM设计模式
MVVM就是帮忙分担一下controller里面的部分业务逻辑。
这个时候,controller将不再直接和真实的model进行绑定了,而通过ViewModel,viewModel进而持有真实的Model。
实例:
//新建一个viewModel
//.h文件
@interface viewModel : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *price;
@property (nonatomic, strong) NSString *discount;
- (id)initWithCustomer:(Customer *)customer iphone:(iPhone *)iphone;
@end
//.m文件
@interface viewModel ()
@property (nonatomic, strong) iPhone *iphone;
@property (nonatomic, strong) Customer *customer;
@end
@implementation viewModel
- (id)initWithCustomer:(Customer *)customer iphone:(iPhone *)iphone
{
if (self = [super init]) {
_customer = customer;
_iphone = iphone;
[self bindData];
}
return self;
}
- (void)bindData
{
self.name = _iphone.name;
self.price = _iphone.price;
if (self.customer.customerType == CustomerTypeStudent) {
self.discount = @"优惠20%";
}
else if (self.customer.customerType == CustomerTypeiT) {
self.discount = @"优惠50%";
}
else {
self.discount = @"没有优惠";
}
}
@end
//VC
@interface ViewController ()
@property (nonatomic, strong) viewModel *viewModel;
@property (weak, nonatomic) IBOutlet UILabel *lblName;
@property (weak, nonatomic) IBOutlet UILabel *lblPrice;
@property (weak, nonatomic) IBOutlet UILabel *lblDiscount;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @"手机优惠";
self.lblName.text = self.viewModel.name;
self.lblPrice.text = self.viewModel.price;
self.lblDiscount.text = self.viewModel.discount;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
看到修改完的代码,你会发现VC里面已经省去了不少的代码。一切都和viewModel进行交流。这里我只是展示一个最简单的数据展示,如果有其他响应事件,是需要viewModel开放方法来进行处理的,并要通知VC处理结果的。
关于MVVM的优点:
- 方便测试
在MVC下,Controller基本是无法测试的,里面混杂了个各种逻辑,而且分散在不同的地方。有了MVVM我们就可以测试里面的viewModel,来验证我们的处理结果对不对(Xcode7的测试已经越来越完善了)。
- 便于代码的移植
比如iOS里面有iPhone版本和iPad版本,除了交互展示不一样外,业务逻辑的model是一致的。这样,我们就可以以很小的代价去开发另一个app。
- 兼容MVC
MVVM是MVC的一个升级版,目前的MVC也可以很快的转换到MVVM这个模式。VC可以省去一大部分展示逻辑。
缺点:
- 类会增多
每个VC都附带一个viewModel,类的数量*2
- viewModel会越来越庞大
我们把逻辑给了viewModel,那势必Model也会变得很复杂,里面的属性和方法越来越多。可能重写的方法比较多,因为涉及到一些数据的转换以及和controller之间的通信。
- 调用复杂度增加
由于数据都是从viewModel来,想想突然来了一个新人,一看代码,不知道真实的模型是谁。比如常用tableview的数据源,一般都是一个数组,如果不断的通过viewModel去取,沟通上没有那么直接。况且每封一层,意味着要写很多代码去融合他们的转换。