一千个程序员眼中有一千种 MVC
MVC.gif
以上是对 MVC 原始论文的整理翻译。
在 MVC 中,V 可以和 C 通信,V 可以和 M 通信。
最早的 MVC 于 1979 年提出,当时还需要程序员全权处理用户输入——Controller 的职责。而现在,大部分事情已经被操作系统做了,我们已经做不到“View 永远不会知道用户的输入”,我们也不太需要 Editor,因为这些已经被封装进UITextField
之类的控件中,View 本身就具备一定的交互功能。用户操作往往被封装成“事件”传递给 View。
所以真正的 MVC 是一种过时的架构。
Apple MVC.png
Apple 所谓的 MVC 跟原始的 MVC 基本已经毫无关系……在这里 C 成了一个中介者,用以协调 V 和 M。
这个模式其实没有特别大的问题,但是由于 Cocoa 中的 ViewController 还承担了 View Container 的工作,我们在日常开发中又容易把 Model 层设计得过于单薄(比如只是一个单纯的数据对象),从而导致 Controller 中有大量本该放在 View 和 Model 中的代码。
所以这是一个最容易被滥用的模式。
MVVM.png
MVVM 由微软架构师 John Gossman 于 1996 年提出,在提出这个概念以前,他们团队早已在实践这个架构了。由于 MVVM 是 MVC 的一种改进,M 和 V 部分和 MVC 是类似的。而 Gossman 认为在现代 GUI 系统中,C 的大部分工作已经由系统帮你做了,所以 C 并没有被抛弃,而是隐藏到幕后了。
MVVM 中的 VM 承担了状态管理、数据转换、操作处理之类的任务,它早先被用于 WPF(View 层由 XMAL 编写,且内建了绑定机制),但写 WPF 并不一定要用 MVVM,你完全可以将 View 和 Model 直接绑定——如果你的程序足够简单。
由于在 iOS 中并没有一个内建的绑定机制,很多人觉得在项目中多一层数据转换层就是 MVVM 了,这有一些片面。我还是觉得真的要用 MVVM 就必须建立一套绑定机制,可以利用 RxSwift 和 RAC 之类的第三方库,或者自己撸一套。
Passive View variant of MVP.png
1996年,Mike Potel 在一篇论文中提出 Model-View-Presenter 的概念。这个时候的 View 已经跟 MVC 刚诞生时的 View 全然不同了,它可以接受用户输入。MVP 的主要思想是用户输入由 V 流进,V 通过 P 更新 M,同时 V 跟 M 之间还是跟 MVC 中一样,V 可以调用 M 的接口,M 通过观察者模式向 V 广播自身的更新。
同 MVC 一样,而今的 MVP 与最早的 MVP 也相距甚远。现在为人所普遍接受的 MVP 是,V 和 M 完全解耦,通过 P 进行通讯。但和 Apple MVC 不同的是,P 并不包含生命周期控制之类的职责,而且一般是由 V 去持有 P。
MVP 似乎在 Android 开发中比较流行,我没有实践过,不敢妄言。
VIPER.png
由 View、Interactor、Presenter、Entity、Router 组成。
同样没有实践过……但直观上感觉是把 MVP 进行了进一步拆分——Presenter 拆为 Presenter 和 Router,Model 拆为 Interactor 和 Entity。
对于结构划分,还是要根据项目规模来,规模大就分层细一点,规模小就粗一点。因为分层越多,层与层之间的通信成本就越高。通信方面可以采取各种手段——接口调用、观察监听、数据绑定等。
我个人比较倾向于分为 View、Model、ViewModel、Router 这几层,以数据绑定为基础进行通信。
各个层最好都定义一个协议来确认各自的职责,可以有一些默认实现。