MVC
模型(Model)- 视图(View)- 控制器(Controller)
目的:将Model与View的实现代码分离
Apple的MVC中:
- Model:存储数据,不负责如何展示数据,Model层最好就是负责纯粹的数据结构,响应的数据操作可以放到扩展中。
- View:对Model中的数据进行展示,与用户交互
- Controller:
- Model与View之间的连接器,控制程序的流程,处理事件并做出响应
- 为应用程序执行设置和协调任务,管理其他对象的声明周期
传统的MVC
iOS 理想MVC示意图
- Model与View只能通过Controller通信
- Cotroller直接读写调用Model,Model通过KVO或Notification与Controller间接通信
- Cotroller与View直接对话,通过outlet操作View,View通过delegate向Controller提交事件
- Controller是View的直接数据源(数据可能是Controller从Model中取得并加工过)
苹果推荐的MVC事实
- View绑定在ViewController上
- 业务逻辑和展示逻辑全部放在ViewController中
- View与Model直接进行交互,耦合性严重
MVC的不足
- 愈发臃肿的Controller
- 太过轻量的Model
- 遗失的网络逻辑
- 较差的可测试性
MVP
MVP属于Presentation层的设计模式
目的:显示逻辑与业务逻辑分离,提高自动化单元测试
- Model:模块的业务逻辑和数据的提供者
- View:数据的可视化呈现
- Presenter:从Model中取出数据,并格式化展示在View中
通常View会实例化Presenter对象,并提供对自身的引用
Model、Presenter、View之间的通信:
- Model和View使用Observer模式沟通
- Presenter与View使用Mediator模式沟通
- Presenter使用Command模式控制Model
MVP中,用户请求首先到达View层,在由View层调用Presenter层,Presenter从Model去数据,处理后,调用View 层更新
MVP变体较多,常用的变体为Passive View(被动 视图),其特点:
- View、Model不直接交互,View通过Presenter与Model打交道
- Presenter接受View的UI请求,处理简单的UI逻辑(即View调用Presenter接口)
- Presenter调用Model处理业务逻辑,并调用View展示结果(即Presenter调用View接口)
在Passive View中,主动的是Presenter:
- Presenter是MVP体系的控制中心,并非单纯的处理View的请求
- Presenter是View与Model之间的协调者,根据交互逻辑给View和Model安排工作
- View仅作为交互请求的汇报者,响应的交互逻辑由Presenter处理
- 绑定在View上的数据,应由Presenter主动推送,而不是由View主动拉取
- View尽可能不维护数据的状态,仅单纯的实现独立的UI操作
缺点:MVP中Presenter与View互相持有,导致Presenter服用性差
iOS的MVP中,View的角色由ViewController扮演,而不是UIView
误区
- 把Presenter视为View调用Model的中介,Presenter变为Proxy
- UI处理逻辑大部分写在View中,Presenter仅影响View对Model的调用
MVVM
MVVM:由MVP模式与WPF技术结合演变的一种使用数据绑定的基础架构
MVVM中View与ViewModel没有MVP的界面接口,而是采用数据绑定的形式让数据更新的事件不需要开发人员手动去编写特殊用例
Model:
View:
ViewModel:一个值转换器,负责将Model转换成易于管理和展示的数据对象。
- ViewModel与View之间可以使用Mediator模式
- ViewModel与MVC的C和MVP的P不同,具有绑定器
viewModel持有model
对于可变 Model,我们还需要使用一些绑定机制,这样 View Model 就能在背后的 Model 改变时更新自身的属性。此外,一旦 View Model 上的 Model 发生改变,那 View 的属性也需要更新。Model 的改变应该级联向下通过 View Model 进入 View。
MVVM的两个原则:
- View持有ViewModel的引用
- ViewModel持有Model的引用
iOS中目前只能通过RAC来完成双向绑定
MVVM优点:
- 兼容当下的MVC
- 增加可测试性
- 配合绑定机制更好,简化了业务与界面的依赖方式,还优化了数据频繁更新的解决方案
没有使用双向绑定的MVVM,与MVP区别不大,在数据驱动界面展示的情况下,必须先修改数据源,然后在刷新界面,如果直接修改界面展示,则要注意将最新的界面状态刷回数据源,否则会出现问题,一些情况下,可能只修改了界面的一个属性,但是却要把整个数据源刷一遍就有些就会耗时,显得很多余,如果使用双向绑定,则可以解决这些问题。
为什么MVP、MVVM中P/VM要使用中介者模式与V通信
- MVP中,P和V交互需要将接口暴露给对方,在业务逻辑不复杂,或者V层的复用性不大的情况下,P和V互相持有是最为简便的做法
- MVP中V会持有P、MVVM中V会持有VM,导致V与P/VM绑定在一起,如果想要在其他地方复用V但业务逻辑不太一样,相应的业务逻辑就增加在之前的P或者VM里面了,导致P和VM逻辑变得复杂和臃肿
- 通过中介者模式,将V与P/VM进行解耦,相当于给V增加了一个Controller,MVP/MVVM编程了MVCP/MVCVM模式,此时的View层仅仅负责展示逻辑,数据的绑定以及和上层的交互,交给了中介者C层进行了处理
iOS 架构模式--解密MVC,MVP,MVVM以及VIPER架构
杂谈: MVC/MVP/MVVM
浅谈MVP架构及开发模式
界面之下:还原真实的 MVC、MVP、MVVM 模式
MVVM 介绍
iOS开发之MVVM设计模式
iOS-ReactiveCocoa(RAC)的高级使用之视图与模型的双向绑定
MVVM与Controller瘦身实践