MVC MVP MVVM的区别与联系
mvc模式:从大锅烩时代进化,引入了分层的概念,但是层与层之间耦合明显,维护起来不容易。
mvp模式:在MVC的基础上进一步解耦,视图层和模型层完全隔离,交互只能通过管理层来进行,问题是更新视图需要管理层手动来进行。
mvvm模式:引入双向绑定机制,帮助实现一些更新视图层和模型层的工作,让开发者可以更专注于业务逻辑,相比于之前的模式,可以使用更少的代码量完成更复杂的交互。
MVC、MVP、MVVP模式是我们经常遇到的概念,其中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模式的思路。
典型思路是View层通过事件通知到Controller层,Controller层经过对事件的处理完成相关业务逻辑,要求Model层改变数据状态,Model层再将新数据更新到View层。示意图如下:
在实际操作时,用户可以直接对View层的UI进行操作,以通过事件通知Controller层,经过处理后修改Model层的数据,Model层使用最新的数据更新View。示意图如下:
用户可以直接触发Cotnroller去更新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层的Model层和View层存在耦合,为了解决这个问题,MVP模式将VIew层和Model层解耦,之间的交互只能通过Presenter层,实际上,MVP模式的目的就是将VIew层和Model层完全解耦,使得对View层的修改不会影响到Model层,而对Model层的数据改动也不会影响到View层。
典型流程View层触发的事件传递到Presenter层中处理,Presetner层去操作Model层,并且将数据返回给VIew层,这个过程中,VIew层和Model层没有直接的联系。而View层不部署业务逻辑,除了展示数据和触发事件之外,其它时间都在等着Presenter
层来更新自己,被称为「被动视图」。
示意图如下:
在实际操作时,用户可以直接对VIew层的UI进行操作,View通知Presenter层,Presenter层操作Model层的数据,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 视图模型ViewModel
和MVP类似,Model层和View层也被隔开,彻底解耦,ViewModel层相当于Presenter层,负责绑定Model层和View层,相比于MVP增加了双向绑定机制。
结构图如下:
MVVM模式的特征是ViewMOdel层和View层采用双向绑定的形式(Binding),View层的变动,将自动反映在ViewModel层,反之亦然。
但是双向绑定给调试和错误定位带来困难,View层的异常可能是VIew的问题,也有可能是Model层的问题。数据绑定使得一个位置的Bug被传递到别的位置,要定位原始出问题的地方变得不那么容易了。
对简单的UI来说,实现MVVM模式的开销是不必要的,而对于大型应用来说,引入MVVM模式则会节约大量手动更新视图的复杂过程,是否使用,还是看使用场景。
Vue的双向绑定机制应该算是比较有MVVM模式的影子,但Vue文档里面是这么描述:
这是为什么呢?因为MVVM模式要求Model层和View层完全解耦,但是由于Vue还提供了ref这样的API,使得Model也可以直接持有VIew:
但是大多数帖子都说直接称呼Vue为MVVM模式,可见这睦模式的划分也不是那么严格。