MVC

1、MVC

MVC 的理想模型各层的职责:

  • Models:数据层,负责数据的处理和获取数据接口层。
  • Views:展示层(GUI),对于iOS 来说所有的以UI 开头的类几百本都属于这层。
  • Controller:控制器层,它是Model 和 View 之间的胶水或者说是中间人。一般来说,当用户对View 有操作时它负责去修改相应的 Model ;当Model 的值发生变化时它负责去更新对应的View。
2、MVC 在iOS 里面的实现

但是实际在iOS 里面的实现方式很难做到如上所诉的那样,因为由于Apple 的规范,一个见面的呈现都需要构建一个ViewController ,而每个 ViewController 都带有一个根View ,这样就导致C 和V 紧密的联系在一起构成了iOS 里面的C 层,这明显的违背了 MVC 的初衷。

Apple 里面的MVC 真正写起来大概如下图所示:



这也是massive controller 的由来。

3、iOS的MVC 各层职责

Controller层(VC):

  • 生成View,然后组装View。
  • 响应View的事件。
  • 调用model的数据获取接口,拿回返回数据,加工处理,显然到View。
  • View的生命周期。
  • 处理界面间的跳转

Model层:

  • 业务逻辑。
  • 提供数据接口给Controller。
  • 数据持久化存储和读取。
  • 作为数据模型存储数据。

View 层:

  • 界面元素搭建,动画效果,数据展示。
  • 接受用户操作并反馈视觉效果。
4、massive controller

造成massive controller的原因的罪魁祸首就是apple的把view和Cotroller组合在一起,让VC同时做view和C的事,导致代码量激增,也违背了MVC原则。

理解Model层:

首先要正确的理解MVC中的M是什么?他是数据模型吗?答案是NO。他的正确定义是业务模型。也就是你所有业务数据和业务实现逻辑都应该定义在M层里面,而且业务逻辑的实现和定义应该和具体的界面无关,也就是和视图以及控制之间没有任何的关系,它是可以独立存在的,您甚至可以将业务模型单独编译出一个静态库来提供给第三方或者其他系统使用。 在上面经典MVC图中也很清晰的描述了这一点: 控制负责调用模型,而模型则将处理结果发送通知给控制,控制再通知视图刷新。因此我们不能将M简单的理解为一个个干巴巴的只有属性而没有方法的数据模型。 其实这里面涉及到一个最基本的设计原则,那就是面向对象的基本设计原则:就是什么是类?类应该是一个个具有不同操作和不同属性的对象的抽象(类是属性和方法的集合)。 我想现在任何一个系统里面都没有出现过一堆只有数据而没有方法的数据模型的集合被定义为一个单独而抽象的模型层来供大家使用吧。 我们不能把一个保存数据模型的文件夹来当做一个层,这并不符合横向切分的规则。 Model层实现的正确姿势:

定义的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层的代码不变。

MVP

MVC的缺点在于并没有区分业务逻辑和业务展示, 这对单元测试很不友好. MVP针对以上缺点做了优化, 它将业务逻辑和业务展示也做了一层隔离, 对应的就变成了MVCP。

M和V功能不变, 原来的C现在只负责布局, 而所有的业务逻辑全都转移到了P层。P层处理完了业务逻辑,如果要更改view的显示,那么可以通过回调来实现,这样可以减轻耦合,同时可以单独测试P层的业务逻辑。

MVP从视图层中分离了行为(事件响应)和状态(属性,用于数据展示),它创建了一个视图的抽象,也就是presenter层,而视图就是P层的『渲染』结果。P层中包含所有的视图渲染需要的动态信息,包括视图的内容(text、color)、组件是否启用(enable),除此之外还会将一些方法暴露给视图用于某些事件的响应。

2、MVP架构和各层职责对比



在 MVP 中,Presenter 可以理解为松散的控制器,其中包含了视图的 UI 业务逻辑,所有从视图发出的事件,都会通过代理给 Presenter 进行处理;同时,Presenter 也通过视图暴露的接口与其进行通信。

Presenter层职责:

  • 实现view的事件处理逻辑,暴露相应的接口给view的事件调用
  • 调用model的接口获取数据,然后加工数据,封装成view可以直接用来显示的数据和状态
  • 处理界面之间的跳转(这个根据实际情况来确定放在P还是C)

在MVP里面业务逻辑和业务展示是分在不同的地方实现,那么就可以分开测试二者了,而不想MVC那样想测试下业务逻辑,还必须生成一个view,这不合理,因为业务逻辑改变的model的数据,和view无关。

MVP相对于MVC, 它其实只做了一件事情, 即分割业务展示和业务逻辑. 展示和逻辑分开后, 只要我们能保证V在收到P的数据更新通知后能正常刷新页面, 那么整个业务就没有问题. 因为V收到的通知其实都是来自于P层的数据获取/更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了. 即我们只用测试P层的逻辑, 不必关心V层的情况

MVVM

MVP MVVM 的区别:

MVVM 是在 MVP 的基础上发展起来的。 MVVM各层的职责和MVP的类似,VM对应P层。只是MVVM 在 MVP 的基础上增加了数据绑定。当然不使用双向数据绑定 也是可以实现MVVM 的。

MVVM和MVP相对于MVC最大的改进在于:P或者VM创建了一个视图的抽象,将视图中的状态和行为抽离出来形成一个新的抽象。这可以把业务逻辑(P/VM)和业务展示(V)分离开单独测试,并且达到复用的目的,逻辑结构更加清晰

MVVM相对于MVP做的改进的好处是什么?

相对MVP的view触发P的业务逻辑,然后P再回调改变View的显示的操作,使用MVVM的数据绑定来实现让逻辑更加清晰,代码也更少。这就是MVVM相对于MVP的改进之处