MVP

1 - MVP 是 MVC 设计模式派生出来的,它经常用来创建用户界面

ios viper 架构 ios mvp架构模式_ios viper 架构

 

2 - MVP 工作原理

① MVP 中 Presenter 完全把 Model 和 View 进行了分离,主要的程序逻辑在 Presenter 里实现。模型与视图完全分离,我们可以修改视图而不影响模型

② Presenter 与 View 是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更 View 时可以保持 Presenter 的不变。实际开发中往往可以将一个 Presenter 用于多个 View,而不需要改变 Presenter 的逻辑。这个特性非常的有用,因为 View 的变化总是比 Model 的变化频繁

③ 所有的交互都发生在 Presenter 内部,可以更高效地使用 Model 注:程序逻辑主要在 Presenter 里实现,其中的 Model 是很薄的一层(View 是很简单的,能够把信息显示清楚就可以)

3 - MVP 与 MVC 有着一个重大的区别:在 MVP 中 V 并不直接使用 Model 它们之间的通信是通过 Presenter 来进行的,所有的交互都发生在 Presenter 内部。就算是 Model 和 View 之间存在数据交互,也仅仅提供最简单的 setter/getter

3 - MVP 的好坏

① 好处

    可以编写测试用的 View 模拟用户的各种操作,从而实现对 Presenter 的测试,而再不需要使用自动化的测试工具

Object(实现了 Model 和 View 的接口,但没有具体内容)来测试 Presenter 的逻辑

    注:就是说完全可以脱离用户接口来实现单元测试

② 坏处

    由于对视图的渲染放在了 Presenter 中,所以视图和 Presenter 的交互会过于频繁

    Model 亦是如此,MVP 模式容易造成接口类爆炸、类文件和接口文件过多的问题,从而增大包的体积

MVP 实战

1 - 思路:MVP 在 iOS 中的表现无非就是让 P 承担了 Controller 的功能,M、V 依旧保持不变。实现方法也很简单,我们利用属性只需把 P 和 C 绑定在一起即可(互为彼此:注意循环依赖问题)。目录结构如图

ios viper 架构 ios mvp架构模式_ios viper 架构_02

2 - 代码示例

// - TestView.h

1 #import <UIKit/UIKit.h>
 2 // 制定协议( P 接受)
 3 @protocol TestViewDelegate <NSObject>
 4 
 5 -(void)doSomethings;
 6 
 7 @end
 8 
 9 @interface TestView : UIView
10 
11 @property(nonatomic,strong)UILabel *TVLabel;
12 @property(nonatomic,weak)id<TestViewDelegate>delegate; // 代理
13 
14 // 提供一个简单入口
15 -(void)setName:(NSString *)name withimage:(UIImage *)image;
16 
17 
18 @end

// - TestView.m

1 #import "TestView.h"
 2 @implementation TestView
 3 
 4 - (instancetype)initWithFrame:(CGRect)frame
 5 {
 6     self = [super initWithFrame:frame];
 7     if (self) {
 8         
 9         self.TVLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, self.frame.size.width -40, self.frame.size.height -80)];
10         self.TVLabel.backgroundColor = [UIColor orangeColor];
11         self.TVLabel.textAlignment = NSTextAlignmentCenter;
12         [self addSubview:self.TVLabel];
13         
14     }
15     return self;
16 }
17 
18 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
19     
20     if ([self.delegate respondsToSelector:@selector(doSomethings)]) {
21         [self.delegate doSomethings];
22     }
23 }
24 
25 -(void)setName:(NSString *)name withimage:(UIImage *)image{
26     
27    // 键入你要做的事情
28     
29 }
30 
31 @end

// - TestModel.h

1 #import <Foundation/Foundation.h>
2 @interface TestModel : NSObject
3 
4 // 数据源
5 @property(nonatomic,copy)NSString *name;
6 
7 @end

// - TestPresenter.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TestPresenter : NSObject

// 绑定 Controller:就是为了让 P 拿到 C 来承担 C 的功能
@property(nonatomic,weak)UIViewController *controller;

// 入口方法(初始化)
-(void)setUP;


@end

// - TestPresenter.m

1 #import "TestPresenter.h"
 2 #import "TestView.h"
 3 #import "TestModel.h"
 4 // Presenter 既然替代了 controller 的功能,那么同视图的交互,我们同样采用代理
 5 @interface TestPresenter()<TestViewDelegate> // 接受来自视图的协议
 6 
 7 @end
 8 
 9 @implementation TestPresenter
10 
11 // P 完全负责 V、M 的交互
12 -(void)setUP{
13     NSLog(@"---- P、C 两者绑定成功 -----");
14     
15     // 加载视图
16     TestView *tView = [[TestView alloc] initWithFrame:CGRectMake(30, 80, SCREEN_WIDTH - 60, 200)];
17     tView.backgroundColor = [UIColor redColor];
18     [self.controller.view addSubview:tView];
19     tView.delegate = self;
20     
21     // 加载数据模型
22     TestModel *tModel = [TestModel new];
23     tModel.name = @"QQ";
24     
25     // 赋值
26     tView.TVLabel.text = tModel.name;
27     // V 可向 M 提供简单入口
28     [tView setName:nil withimage:nil];
29 
30 }
31 
32 
33 // 代理
34 - (void)doSomethings{
35     
36     // 随机色
37     self.controller.view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0
38                                                            green:arc4random()%255/255.0
39                                                            blue:arc4random()%255/255.0
40                                                            alpha:1.0];
41 }
42 
43 @end

// - UIViewController.m

1 #import "ViewController.h"
 2 #import "TestPresenter.h"
 3 @interface ViewController()
 4 
 5 // 绑定 Presenter
 6 @property(nonatomic,strong)TestPresenter *presenter;
 7 @end
 8 
 9 @implementation ViewController
10 
11 - (void)viewDidLoad {
12     [super viewDidLoad];
13     self.view.backgroundColor = [UIColor cyanColor];
14     
15     // Presenter
16     self.presenter = [TestPresenter new];
17     self.presenter.controller = self;
18     
19     // 入口方法:在 P 中处理原 C 负责的事
20     [self.presenter setUP];
21     
22 }
23 
24 @end

运行效果

ios viper 架构 ios mvp架构模式_ios viper 架构_03