1、MVC的理想模型
从字面意思来理解,MVC 即 Model View Controller(模型 视图 控制器),是 Xerox PARC 在 20 世纪 80 年代为编程语言 Smalltalk-80 发明的一种软件设计模式,至今已广泛应用于用户交互应用程序中。其用意在于将数据与视图分离开来。在 iOS 开发中 MVC 的机制被使用的淋漓尽致,充分理解 iOS 的 MVC 模式,有助于我们程序的组织合理性。
MVC 的几个明显的特征和体现:
1、View 上面显示什么东西,取决于 Model。
2、只要 Model 数据改了,View 的显示状态会跟着更改。
- Models: 数据层,负责数据的处理和获取的数据接口层。
- Views: 展示层(GUI),对于 iOS 来说所有以 UI 开头的类基本都属于这层。
- Controller:控制器层,它是 Model 和 View 之间的胶水或者说是中间人。一般来说,当用户对 View 有操作时它负责去修改相应 Model;当 Model 的值发生变化时它负责去更新对应 View。
如上图所示,M和View应该是完全隔离的,由C作为中间人来负责二者的交互,同时三者是完全独立分开的,这样可以保证M和V的可测试性和复用性,但是一般由于C都是为特别的应用场景下的M和V做中介者,所以很难复用。
2、MVC在iOS里面的实现
实际上在iOS里面MVC的实现方式很难做到如上所述的那样,因为由于Apple的规范,一个界面的呈现都需要构建一个viewcontroller,而每个viewcontroller都带有一个根view,这就导致C和V紧密耦合在一起构成了iOS里面的C层。
apple里面的MVC真正写起来大概如下图所示:
3、iOS的MVC各层职责
controller层(VC):
1、生成view,然后组装view
2、响应View的事件和作为view的代理
3、调用model的数据获取接口,拿到返回数据,处理加工,渲染到view显示
4、处理view的生命周期
5、处理界面之间的跳转
model层:
1、业务逻辑封装
2、提供数据接口给controller使用
3、数据持久化存储和读取
4、作为数据模型存储数据
view层:
1、界面元素搭建,动画效果,数据展示,
2、接受用户操作并反馈视觉效果
4、MVC中M层实现的准则
-
定义的M层中的代码应该和V层和C层完全无关的,也就是M层的对象是不需要依赖任何C层和V层的对象而独立存在的。整个框架的设计最优结构是V层不依赖C层而独立存在,M层不依赖C层和V层独立存在,C层负责关联二者,V层只负责展示,M层持有数据和业务的具体实现,而C层则处理事件响应以及业务的调用以及通知界面更新。三者之间一定要明确的定义为单向依赖,而不应该出现双向依赖。下面是三层的依赖关系图:
-
M层要完成对业务逻辑实现的封装,一般业务逻辑最多的是涉及到客户端和服务器之间的业务交互。M层里面要完成对使用的网络协议(HTTP, TCP,其他)、和服务器之间交互的数据格式(XML, JSON,其他)、本地缓存和数据库存储(COREDATA, SQLITE,其他)等所有业务细节的封装,而且这些东西都不能暴露给C层。所有供C层调用的都是M层里面一个个业务类所提供的成员方法来实现。也就是说C层是不需要知道也不应该知道和客户端和服务器通信所使用的任何协议,以及数据报文格式,以及存储方面的内容。这样的好处是客户端和服务器之间的通信协议,数据格式,以及本地存储的变更都不会影响任何的应用整体框架,因为提供给C层的接口不变,只需要升级和更新M层的代码就可以了。比如说我们想将网络请求库从ASI换成AFN就只要在M层变化就可以了,整个C层和V层的代码不变。下面是M层内部层次的定义图:
M层如何和C层交互的问题也需要考虑,因为M层是不需要知道C层和V层的存在的,那么M层在业务处理完毕后如何去通知C层呢?方法有很多种:
1、我们可以为M层的通知逻辑定义Delegate协议,然后让C层去实现这些协议,然后M层提供一个delegate属性来赋值处理业务通知的对象。
2、我们也可以定义众多的NSNotification或者事件总线,然后当M层的业务处理完毕后可以发送通知,并且在C层实现通知的处理逻辑。
3、我们可以用闭包回调或者接口匿名实现对象的形式来实现业务逻辑完成的通知功能。
总结来说:
M层不应该是数据模型,放几个属性就完事了。而应该是承载业务逻辑和数据存储获取的职责一层。
5、MVC优缺点
优点:
1、代码复用: 三个小模块的V(cell/userInfoView)对外只暴露Set方法, 对M甚至C都是隔离状态, 复用完全没有问题. 三个大模块的MVC也可以用于快速构建相似的业务场景(大模块的复用比小模块会差一些, 下文我会说明).
2、易拓展性: 当模型,数据与控制器是相分离的时候,改变业务规则就变得很容易,数据的存储可以随意的迁移,因为模型对控制器的接口是不变的,这样界面仍然可以正确的展示,界面UI也是可以任意改变,因为它只关心界面不会影响到其他.
3、可维护性: 各个模块间职责分离, 哪里出错改哪里, 完全不影响其他模块. 利于多人团队开发
缺点:
1、没有区分业务逻辑和业务展示, 这对单元测试很不友好.
2、增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
3、视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
4、业务逻辑和业务展示强耦合: 可以看到, 有些业务逻辑(页面跳转/点赞/分享…)是直接散落在V层的, 这意味着我们在测试这些逻辑时, 必须首先生成对应的V, 然后才能进行测试. 显然, 这是不合理的. 因为业务逻辑最终改变的是数据M, 我们的关注点应该在M上, 而不是展示M的V.
参考博客
iOS MVC、MVVM、MVP详解 - 简书 (jianshu.com)
深入分析MVC、MVP、MVVM、VIPER (juejin.cn)
iOS中MVC设计模式的优缺点_dxm_8888的博客-CSDN博客_ios mvc优点