MVC、MVP、MVVM
MVC模式: 从大锅烩时代进化,引入了分层的概念,但是层与层之间耦合明显,维护起来不容易;MVP模式: 在 MVC 基础上进一步解耦,视图层和模型层完全隔离,交互只能通过管理层来进行,问题是更新视图需要管理层手动来进行;MVVM模式: 引入双向绑定机制,帮助实现一些更新视图层和模型层的工作,让开发者可以更专注于业务逻辑,相比于之前的模式,可以使用更少的代码量完成更复杂的交互; MVC、MVP、MVVM 模式是我们经常遇到的概念,其中 MVVM 是最常用到的,在实际项目中往往没有严格按照模式的定义来设计的系统,开发中也不一定要纠结自己用的到底是哪个模式,合适的才是最好的。
1. MVC (Model View Controller)
MVC模式将程序分为三个部分:模型(Model)、视图(View)、控制器(Controller)。
Model模型层: 业务数据的处理和存储,数据更新后更新;View视图层: 人机交互接口,一般为展示给用户的界面;Controller控制器层 : 负责连接Model层和View层,接受并处理View层触发的事件,并在Model层的数据状态变动时更新View层;MVC模式的目的是通过引入Controller层来将Model层和View层分离,分层的引入是原来大锅烩方式的改进,使得系统在可维护性和可读性上有了进步。MVC模式提出已经有四十余年,MVC模式在各个书、各个教程、WIKI的解释有各种版本,甚至MVC模式在不同系统中的具体表现也不同,这里只介绍典型MVC模式的思路。
image典型思路是
View层通过事件通知到Controller层,Controller层经过对事件的处理完成相关业务逻辑,要求Model层改变数据状态,Model层再将新数据更新到View层。示意图如下:
image在实际操作时,用户可以直接对
View层的UI进行操作,以通过事件通知Controller层,经过处理后修改Model层的数据,Model层使用最新数据更新View。示意图如下:
用户也可以直接触发 Controller 去更新 Model 层状态,再更新 View 层:
某些场景下,
View层直接采用观察者/发布订阅模式监听Model层的变化,这样View层和Model层相互持有、相互操作,导致紧密耦合,在可维护性上有待提升。由此,MVP模式应运而生 。
2. MVP (Model View Presenter)
MVP模式将程序分为三个部分:模型(Model)、视图(View)、管理层(Presenter)。
Model模型层: 只负责存储数据,与View呈现无关,也与UI处理逻辑无关,发生更新也不用主动通知View;View视图层: 人机交互接口,一般为展示给用户的界面;Presenter管理层 : 负责连接Model层和View层,处理View层的事件,负责获取数据并将获取的数据经过处理后更新View;MVC模式的View层和Model层存在耦合,为了解决这个问题,MVP模式将View层和Model层解耦,之间的交互只能通过Presenter层,实际上,MVP模式的目的就是将View层和 Model 层完全解耦,使得对View层的修改不会影响到Model层,而对Model层的数据改动也不会影响到View层。
典型流程是
View层触发的事件传递到Presenter层中处理,Presenter层去操作Model层,并且将数据返回给View层,这个过程中,View层和Model层没有直接联系。而View层不部署业务逻辑,除了展示数据和触发事件之外,其它时间都在等着Presenter层来更新自己,被称为「被动视图」。
示意图如下:
imageimage在实际操作时,用户可以直接对
View层的UI进行操作,View层通知Presenter层,Presenter层操作Model层的数据,Presenter层获取到数据之后更新View。示意图如下:
- 由于
Presenter层负责了数据获取、数据处理、交互逻辑、UI效果等等功能,所以Presenter层就变得强大起来,相应的,Model层只负责数据存储,而View层只负责视图,Model和View层的责任纯粹而单一,如果我们需要添加或修改功能模块,只需要修改Presenter层就够了。由于Presenter层需要调用View层的方法更新视图,Presenter层直接持有View层导致了Presenter对View的依赖。
正如上所说,更新视图需要
Presenter层直接持有View层,并通过调用View层中的方法来实现,还是需要一系列复杂操作,有没有什么机制自动去更新视图而不用我们手动去更新呢,所以,MVVM模式应运而生。
3. MVVM (Model View ViewModel)
MVVM模式将程序分为三个部分:模型(Model)、视图(View)、视图模型(View-Model)。
和 MVP 模式类似,Model 层和 View 层也被隔离开,彻底解耦,ViewModel 层相当于 Presenter 层,负责绑定 Model 层和 View 层,相比于 MVP 增加了双向绑定机制。
结构图如下:
image
MVVM模式的特征是ViewModel层和View层采用双向绑定的形式(Binding),View层的变动,将自动反映在ViewModel层,反之亦然。
- 但是双向绑定给调试和错误定位带来困难,
View层的异常可能是View的代码有问题,也有可能是Model层的问题。数据绑定使得一个位置的Bug被传递到别的位置,要定位原始出问题的地方就变得不那么容易了。 - 对简单
UI来说,实现MVVM模式的开销是不必要的,而对于大型应用来说,引入 MVVM 模式则会节约大量手动更新视图的复杂过程,是否使用,还是看使用场景。 Vue的双向绑定机制应该算是比较有MVVM模式的影子,但Vue文档 里面是这么描述:
image这是为什么呢,因为
MVVM模式要求Model层和View层完全解耦,但是由于Vue还提供了ref这样的API,使得Model也可以直接持有View:
但是大多数帖子都说直接称呼 Vue 为 MVVM 框架,可见这些模式的划分也不是那么严格。
