iOS基础 - 架构模式:MVP
▶ 什么是 MVP
MVP 是 MVC 设计模式派生出来的,它经常用来创建用户界面
MVP 工作原理
A. MVP 中 Presenter 完全把 Model 和 View 进行了分离,主要的程序逻辑在 Presenter 里实现。模型与视图完全分离,我们可以修改视图而不影响模型
B. Presenter 与 View 是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更 View 时可以保持 Presenter 的不变。实际开发中往往可以将一个 Presenter 用于多个 View,而不需要改变 Presenter 的逻辑。这个特性非常的有用,因为 View 的变化总是比 Model 的变化频繁
C. 所有的交互都发生在 Presenter 内部,可以更高效地使用 Model
注:程序逻辑主要在 Presenter 里实现,其中的 Model 是很薄的一层;View 也是很简单的,能够把信息显示清楚就可以
MVP 与 MVC 有着一个重大的区别:MVP 中 V 并不直接使用 Model,它们之间的通信是通过 Presenter 来进行的,所有的交互都发生在 Presenter 内部!就算是 Model 和 View 之间存在数据交互,也仅仅提供最简单的 setter/getter
MVP 的缺点/优点
A. 好处
可以编写测试用的 View 模拟用户的各种操作,从而实现对 Presenter 的测试,而再不需要使用自动化的测试工具
可以在 Model 和 View 都没有完成时候就可以通过编写 Mock Object(实现了 Model 和 View 的接口,但没有具体内容)来测试 Presenter 的逻辑
注:就是说完全可以脱离用户接口来实现单元测试
B. 坏处
由于对视图的渲染放在了 Presenter 中,所以视图和 Presenter 的交互会过于频繁
Model 亦是如此,MVP 模式容易造成接口类爆炸、类文件和接口文件过多的问题,从而增大包的体积
▶ MVP 实战
MVP 在 iOS 中的表现无非就是让 P层 承担了 Controller 的功能,M、V 两层依旧保持不变。实现方法也很简单,我们只需利用属性把 P层 和 C层 绑定在一起即可(互为彼此时注意循环依赖问题)
具体实现:首先将 P层 和 C层绑定;其次 P层 完全充当了 C层 的功能:比如创建视图、数据交互....
// - UIViewController.m
#import "ViewController.h" #import "TestPresenter.h" @interface ViewController() // 绑定 Presenter @property(nonatomic,strong)TestPresenter *presenter; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor cyanColor]; // Presenter self.presenter = [TestPresenter new]; self.presenter.controller = self; // 入口方法:在 P 中处理原 C 负责的事 [self.presenter setUP]; } @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:所有的事情全部在 P层 处理
1 #import "TestPresenter.h" 2 #import "TestView.h" 3 #import "TestModel.h" 4 @interface TestPresenter()<TestViewDelegate> // 接受协议 5 6 @end 7 8 @implementation TestPresenter 9 10 // P 完全负责 V、M 的交互 11 -(void)setUP{ 12 NSLog(@"---- P、C 两者绑定成功 -----"); 13 [self makeSomethings]; 14 } 15 16 -(void)makeSomethings{ 17 18 // 加载视图 19 TestView *tView = [[TestView alloc] initWithFrame:CGRectMake(30, 80, self.controller.view.frame.size.width - 60, 200)]; 20 tView.backgroundColor = [UIColor redColor]; 21 [self.controller.view addSubview:tView]; 22 tView.delegate = self; 23 24 // 加载数据模型 25 TestModel *tModel = [TestModel new]; 26 tModel.name = @"QQ"; 27 28 // 赋值 29 tView.TVLabel.text = tModel.name; 30 // V 可向 M 提供一些简单入口进行交互 31 [tView setName:tModel.name withimage:nil]; 32 } 33 34 // 代理:随机色 35 - (void)doSomethings{ 36 self.controller.view.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 37 green:arc4random()%255/255.0 38 blue:arc4random()%255/255.0 39 alpha:1.0]; 40 } 41 42 @end
// - TestView.h
#import <UIKit/UIKit.h> @protocol TestViewDelegate <NSObject> // 协议原本是用来为 C层 制定的,现在 P层 充当了 C层的功能 // 所以我们要在 P层 中接受该协议 -(void)doSomethings; @end @interface TestView : UIView @property(nonatomic,strong)UILabel *TVLabel; @property(nonatomic,weak)id<TestViewDelegate>delegate; // 代理 // V层 可为 M层 提供一些简单入口 -(void)setName:(NSString *)name withimage:(UIImage *)image; @end
// - TestView.m
#import "TestView.h" @implementation TestView - (instancetype)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { self.TVLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 40, self.frame.size.width -40, self.frame.size.height -80)]; self.TVLabel.backgroundColor = [UIColor orangeColor]; self.TVLabel.textAlignment = NSTextAlignmentCenter; [self addSubview:self.TVLabel]; } return self; } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ if ([self.delegate respondsToSelector:@selector(doSomethings)]) { [self.delegate doSomethings]; } } -(void)setName:(NSString *)name withimage:(UIImage *)image{ // 可根据 M层 的数据进行 UI布局 } @end
// - TestModel.h
#import <Foundation/Foundation.h> @interface TestModel : NSObject @property(nonatomic,copy)NSString *name;// 数据源 @end
运行效果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)