MVC、MVVM、MVP、VIPER架构设计模式
https://www.cnblogs.com/oc-bowen/p/6255475.html
架构模式
MV(X)系列概要
当今我们已经有很架构设计模式方面的选择:
- MVC
- MVP ---> 面向协议编程
- MVVM ---> 双向绑定 <--可+-->(函数式编程ReactiveCocoa框架)【函数式编程(Functional Programming)和响应式编程(React Programming)】
- VIPER
前三种设计模式都把一个应用中的实体分为以下三类:
- Models--负责主要的数据或者操作数据的数据访问层,可以想象 Perspn 和 PersonDataProvider 类。
- Views--负责展示层(GUI),对于iOS环境可以联想一下以 UI 开头的所有类。
- Controller/Presenter/ViewModel--负责协调 Model 和 View,通常根据用户在View上的动作在Model上作出对应的更改,同时将更改的信息返回到View上。
将实体进行划分给我们带来了以下好处:
- 更好的理解它们之间的关系
- 复用(尤其是对于View和Model)
- 独立的测试
(1)MVC


MVC一系列的特征:
- 任务均摊--View和Model确实是分开的,但是View和Controller却是紧密耦合的
- 可测试性--由于糟糕的分散性,只能对Model进行测试
- 易用性--与其他几种模式相比最小的代码量。熟悉的人很多,因而即使对于经验不那么丰富的开发者来讲维护起来也较为容易。
如果你不想在架构选择上投入更多精力,那么Cocoa MVC无疑是最好的方案,而且你会发现一些其他维护成本较高的模式对于你所开发的小的应用是一个致命的打击。
“就开发速度而言,Cocoa MVC是最好的架构选择方案。”
(2)MVP

这看起来不正是苹果所提出的MVC方案吗?确实是的,这种模式的名字叫做MVC,但是,这就是说苹果的MVC实际上就是MVP了?不,并不是这样的。如果你仔细回忆一下,View是和Controller紧密耦合的,但是MVP的协调器Presenter并没有对ViewController的生命周期做任何改变,因此View可以很容易的被模拟出来。在Presenter中根本没有和布局有关的代码,但是它却负责更新View的数据和状态。
MVP一特性的分析:
- 任务均摊--我们将最主要的任务划分到Presenter和Model,而View的功能较少(虽然上述例子中Model的任务也并不多)。
- 可测试性--非常好,由于一个功能简单的View层,所以测试大多数业务逻辑也变得简单
- 易用性--在我们上边不切实际的简单的例子中,代码量是MVC模式的2倍,但同时MVP的概念却非常清晰
“iOS 中的MVP意味着可测试性强、代码量大。”
(3)MVVM

MVVM 的作用和问题
MVVM 在实际使用中,确实能够使得 Model 层和 View 层解耦,但是如果你需要实现 MVVM 中的双向绑定的话,那么通常就需要引入更多复杂的框架来实现了。
第一点:数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
第二点:对于过大的项目,数据绑定需要花费更多的内存。
ReactiveCocoa
函数式编程(Functional Programming)和响应式编程(React Programming)也是当前很火的两个概念,它们的结合可以很方便地实现数据的绑定。于是,在 iOS 编程中,ReactiveCocoa 横空出世了,它的概念都非常 新,包括:
- 函数式编程(Functional Programming),函数也变成一等公民了,可以拥有和对象同样的功能,例如当成参数传递,当作返回值等。看看 Swift 语言带来的众多函数式编程的特性,就你知道这多 Cool 了。
- 响应式编程(React Programming),原来我们基于事件(Event)的处理方式都弱了,现在是基于输入(在 ReactiveCocoa 里叫 Signal)的处理方式。输入还可以通过函数式编程进行各种 Combine 或 Filter,尽显各种灵活的处理。
- 无状态(Stateless),状态是函数的魔鬼,无状态使得函数能更好地测试。
- 不可修改(Immutable),数据都是不可修改的,使得软件逻辑简单,也可以更好地测试。
(4)VIPER--把LEGO建筑经验迁移到iOS app的设计

VIPER
- 交互器 -- 包括关于数据和网络请求的业务逻辑,例如创建一个实体(数据),或者从服务器中获取一些数据。为了实现这些功能,需要使用服务、管理器,但是他们并不被认为是VIPER架构内的模块,而是外部依赖。
- 展示器 -- 包含UI层面的业务逻辑以及在交互器层面的方法调用。
- 实体 -- 普通的数据对象,不属于数据访问层次,因为数据访问属于交互器的职责。
- 路由器 -- 用来连接VIPER的各个模块。
当我们把VIPER和MV(X)系列作比较时,我们会在任务均摊性方面发现一些不同:
- Model 逻辑通过把实体作为最小的数据结构转换到交互器中。
- Controller/Presenter/ViewModel的UI展示方面的职责移到了Presenter中,但是并没有数据转换相关的操作。
- VIPER是第一个通过路由器实现明确的地址导航模式。
“找到一个适合的方法来实现路由对于iOS应用是一个挑战,MV(X)系列避开了这个问题。”
VIPER一特性的分析:
- 任务均摊 -- 毫无疑问,VIPER是任务划分中的佼佼者。
- 可测试性 -- 不出意外地,更好的分布性就有更好的可测试性。
- 易用性 -- 最后你可能已经猜到了维护成本方面的问题。你必须为很小功能的类写出大量的接口。
因此,在同一个应用中包含着多种架构。比如,你开始的时候使用MVC,然后突然意识到一个页面在MVC模式下的变得越来越难以维护,然后就切换到MVVM架构,但是仅仅针对这一个页面。并没有必要对哪些MVC模式下运转良好的页面进行重构,因为二者是可以并存的。
有一些人总是追赶着技术,有什么新技术不管三七二十一立马就用,结果被各种坑。
又有一些人,总是担心新技术带来的技术风险,不愿意学习。结果现在还有人在用 MRC 手动管理引用计数。
而我想说,我们需要保持的是一个拥抱变化的心,以及理性分析的态度。在新技术的面前,不盲从,也不守旧,一切的决策都应该建立在认真分析的基础上,这样才能应对技术的变化。