文章目录
- 什么是MVP模式?
- 图解
- 从MVC到MVP
- 苹果的MVC
- 为何要从MVC到MVP?
- MVP
- MVP模式下的工程
- MVP模式的优缺点
什么是MVP模式?
MVP模式是MVC模式的一个演化版本,MVP全称Model-View-Presenter。(关于MVC模式可见这篇文章)
- Model:与MVC中的model没有太大的区别。主要提供数据的存储功能,一般都是用来封装网络获取的
json
数据的集合。Presenter通过调用Model进行对象交互。 - View:这里的View与MVC中的V又有一些小差别,这个View可以是
viewcontroller
、view
等控件。Presenter通过向View传model数据进行交互。 - Presenter:作为Model和View的中间人,从Model层获取数据之后传给View,使得View和Model没有耦合。
图解
- 如图中所示,MVP的 V 层是由
UIViewController
和UIView
共同组成 - View 将委托Presenter 对它自己的操作,简单来说就是Presenter发命令来控制View的交互。
- Presenter跟Model层通信,并将数据转化成对适应UI的数据并更新View
- View层是单一,因为它是被动接受命令,没有主动能力
Presenter 作为业务逻辑的处理者,首先要拿数据赋值给Model,所以它将可以向Model层通信。其次,UI的处理权移交给了它,所以它需要与View成通讯,发送命令更新UI。同时,UI的响应将触发业务逻辑的处理,所以View 层向Presenter层通讯,告诉他用户做了什么操作,需要你反馈对应的数据来更新UI。这样就完成了从用户交互获得交互反馈到整个业务逻辑。
从MVC到MVP
- MVC的缺点在于并没有区分业务逻辑和业务展示, 这对单元测试很不友好。而MVP针对以上缺点做了优化, 它将业务逻辑和业务展示也做了一层隔离, 对应的就变成了MVCP. M和V功能不变, 原来的C现在只负责布局(也就可以说VC就是V), 而所有的逻辑全都转移到了P层。
苹果的MVC
- Controller是View和Model之间的中介,这样他们就解耦了。最小的可重用单元是Controller,这对我们来说是个好消息,因为我们必须有一个来放那些不适合放入Model的复杂业务逻辑的地方。
- 从理论上讲,它看起来很简单,但你觉得有些地方不对,对吧?你甚至听到有人说MVC全称应该改为Massive View Controller(大量的视图控制器)。此外,为View Controller减负也成为iOS开发者面临的一个重要话题。
为何要从MVC到MVP?
MVC的缺点在于并没有区分业务逻辑和业务展示, 这对单元测试很不友好。而MVP针对以上缺点做了优化, 它将业务逻辑和业务展示也做了一层隔离,
对应的就变成了MVCP. M和V功能不变, 原来的C现在只负责布局(也就可以说VC就是V), 而所有的逻辑全都转移到了P层.
MVP
- 这看起来不正是苹果的MVC吗?是的,它的名字是MVP(Passive View variant,被动视图变体)。等等…这是不是意味着苹果的MVC实际上是MVP?不,不是这样。如果你仔细回忆一下,View是和Controller紧密耦合的,但是MVP的中介Presenter并没有对
ViewController
的生命周期做任何改变,因此View可以很容易的被模拟出来。在Presenter中根本没有和布局有关的代码,但是它却负责更新View的数据和状态。 - MVP大概就是这个样子了, 相对于MVC, 它其实只做了一件事情, 即分割业务展示和业务逻辑。 展示和逻辑分开后, 只要我们能保证V在收到P的数据更新通知后能正常刷新页面, 那么整个业务就没有问题。因为V收到的通知其实都是来自于P层的数据获取 / 更新操作, 所以我们只要保证P层的这些操作都是正常的就可以了。即我们只用测试P层的逻辑, 不必关心V层的情况。
MVP模式下的工程
如下是MVP模式下一个demo的结构
- 其中
viewController
类则是UI层,Presenter向UI层发送命令,其实是发给UI层的viewController
,实际上是控制器来被动的更新UI。这个不管是MVC还是MVP,View的实际控制权应该都是viewController
。
MVP模式的优缺点
优点:
- 任务均摊 :我们将最主要的任务划分到 Presenter 和 Model,而 View 的功能较少;
- 可测试性 : 非常好,由于一个功能简单的 View 层,所以测试大多数业务逻辑也变得简单;
- 易用性 : 代码量比 MVC 模式的大,但同时 MVP 的概念却非常清晰。
- 模型与视图完全分离,我们可以修改视图而不影响模型。
- 可以更高效地使用模型,因为所有的交互都发生在一个地方 —— Presenter内部。
- 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
- 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。
缺点:
- 视图和Presenter的交互会过于频繁,使得他们的联系过于紧密。也就是说,一旦视图变更了,Presenter也要变更。