现在我们面对架构设计模式的时候有了很多选择:
- MVC
- MVP
- MVVM
- VIPER
首先前三种模式都是把所有的实体归类到了下面三种分类中的一种:
- Models(模型)数据层,或者负责处理数据的 数据接口层。
- Views(视图)展示层(GUI)。对于 iOS理论上来来说所有以 UI 开头的类基本都属于这层。
- Controller/Presenter/ViewModel(控制器/展示器/视图模型)
它是 Model 和 View 之间的胶水或者说是中间人。
一般来说,当用户对 View 有操作时它负责去修改相应 Model;当 Model 的值发生变化时它负责去更新对应 View。
demo在最下面
一、MVC
MVC是模型 (model)-视图 (view)-控制器 (controller) 的缩写。它表示的是一种常见的客户端软件开发框架。
(1)首先看看MVC它原来的样子
传统MVC经典MVC模式在提出时,大致是上图这样的。在这种架构下,View 是没有状态的,在Model变化的时候它只是简单的被 Controller重绘,尽管这种架构可以在应用里面实现,但是由于 MVC 的三种实体被紧密耦合着,每一种实体都和其他两种有着联系,所以即便是实现了也没有什么意义。
(2)理想化的MVC,也就是苹果的MVC
View 和 Model 之间是相互独立的,它们只通过 Controller 来来负责二者的交互。这样的设计,使得View 和 Model 直接解耦合了。
(3)现实中的MVC
MVC 鼓励编写大规模的视图控制器,因为 View 的整个生命周期都需要它去管理,Controller 和 View 很难做到相互独立。
虽然你仍有能力将一些业务逻辑和数据转换成Model,但你没办法将View从Controller中分离。在大多数情况下,View的责任是把事件传递给Controller。
Controller最终演变成一个其他人的delegate和data source,甚至还负责网络请求的发起和取消,另一方面Controller负责了界面跳转的操作,界面跳转的相关配置是直接在对应的Controller实例上设置的,这样就很容易把源界面和目的界面耦合起来,表现在导入很多其他头文件。最后变得臃肿不堪,所以又称之为Massive View Controller(大量的视图控制器)。
在许多情况下,你见到的代码类似于这样:
cell.model = self.dataArray[indexPath.row];
Model和View经常会直接通信,产生了耦合。
二、MVP
MVP架构MVC的缺点在于并没有区分
业务逻辑和业务展示
,这对单元测试很不友好。
MVP针对以上缺点做了优化,它将业务逻辑和业务展示
也做了一层隔离, 对应的就变成了MVCP。
M和V功能不变,原来的C现在只负责布局,而所有的业务逻辑全都转移到了P层。
P层处理完了业务逻辑,如果要更改view的显示,那么可以通过回调来实现,这样可以减轻耦合,同时可以单独测试P层的业务逻辑。在 MVP 中,P可以理解为松散的控制器,其中包含了视图的 UI 业务逻辑,所有从视图发出的事件,都会通过代理方法Protocol给 P 进行处理;同时,P也通过视图暴露的接口与其进行通信。
- View负责界面展示和布局管理,向Presenter暴露视图更新和数据获取的接口
- Presenter负责接收来自View的事件,通过View提供的接口更新视图,并管理Model
- Model和MVC中的一样,提供数据模型
这个流程看起来确实很像 Apple 的理想化的MVC,它的名字是 MVP(被动变化的 View)。
Apple 的 MVC 实际上是 MVP 吗?不是的
区别就是IOS中:
(1)苹果的理想MVC中UIView相当于View,UIController是Controller,而在MVP中,UIView和UIController都相当于View,所以在 Presenter 里面基本没什么布局相关的代码,它的职责只是通过数据和状态更新 View。
(2)持有关系也不一样,MVC中 C 持有 M和V,但是在MVP中 V 持有 P,P 持有M 。
MVP相对于MVC,它其实只做了一件事情,即分割业务展示和业务逻辑. 展示和逻辑分开后,只要我们能保证V在收到P的数据更新通知后能正常刷新页面,那么整个业务就没有问题。因为V收到的通知其实都是来自于P层的数据获取/更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了。 即我们只用测试P层的逻辑,不必关心V层的情况。
所以MVP实现了各模块的解藕,具有更好的可测试性。但是总体代码量比MVC大。
三、MVVM
MVVM架构 MVVM其实是在MVP的基础上发展起来的。那么MVVM在MVP的基础上改良了啥呢?答案就是数据绑定。
MVVM各层的职责和MVP的类似,viewModel对应P层,只是在MVVM的View层多了数据绑定的操作。
- 在MVVM 中,View和Controller正式联系在一起,我们把它们视为一个组件
- View和Controller 都不能直接引用model,而是引用视图模型(viewModel)
- viewModel 是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他代码的地方
- 使用MVVM会轻微的增加代码量,但总体上减少了代码的复杂性。
MVVM 的使用建议
- MVVM 配合一个绑定机制效果最好(ReactiveCocoa,KVO)。
- Controller 尽量不涉及业务逻辑,让 viewModel 去做这些事情。
- Controller 只是一个中间人,接收 view 的事件、调用 viewModel 的方法、响应 viewModel 的变化。
- viewModel 绝对不能包含视图 view(UIKit.h),不然就跟 view 产生了耦合,不方便复用和测试。
- viewModel之间可以有依赖。
- viewModel避免过于臃肿,否则重蹈Controller的覆辙,变得难以维护。
MVVM优点
- MVVM 可以兼容你当下使用的MVC架构。
- MVVM 增加你的应用的可测试性。
- 低耦合:View 可以独立于Model变化和修改,一个 viewModel 可以绑定到不同的 View 上
- 可重用性:可以把一些视图逻辑放在一个 viewModel里面,让很多 view 重用这段视图逻辑
- 独立开发:开发人员可以专注于业务逻辑和数据的开发 viewModel,设计人员可以专注于页面设计
- 可测试:通常界面是比较难于测试的,而 MVVM 模式可以针对 viewModel来进行测试
缺点
- 学习成本和开发成本都很高,新人很难上手
- iOS中,并没有现成的绑定机制可用,要么使用 KVO,要么引入类似 ReactiveCocoa 这样的第三方库
- 数据绑定使 Debug 变得更难了,堆栈结构更复杂了,使得对象生命周期很难追踪
- 对于过大的项目,数据绑定需要花费更多的内存
- ReactiveCocoa 在国内外还都是在小众领域,没有被大量接受成为主流的编程框架。在别的语言中,例如 Java 中的 RxJava 也同样没有成为主流
网友评论