界面之下:还原真实的MV*模式
说说MVVM

现在市面上架构 MVC\MVP\MVVM
其中各个架构下分为具体不一样的:
MVC:

MVP
MVVM

架构就是分层,在开发应用程序的时候,以求更好的管理应用程序的复杂性,基于职责分离(Speration of Duties)的思想都会对应用程序进行分层
view:用户界面
model:应用程序的数据

MV*解读 - 图1

基础底层就是V&M,无论是MV什么,我们核心要解决的问题都是——View如何同步Model的变更,View和Model之间如何粘合在一起?
而这些模式的差异其实可以归结于——核心问题的处理方式不一样,且所有的MV
模式都是从经典的Smalltalk-80 MVC修改而来。

MVC

image.png image.png
control作为中间一层 核心是为了协作,吊车的作用吧

需要注意的点:

  1. View是把控制权交移给Controller,Controller执行应用程序相关的应用逻辑(对来自View数据进行预处理、决定调用哪个Model的接口等等)。
  2. Controller操作Model,Model执行业务逻辑对**数据**进行处理。但不会直接操作View,可以说它是对View无知的(view并不知道model的存在)
  3. View和Model的同步消息是通过**观察者模式**进行,而同步操作是由View自己请求Model的数据然后对视图进行更新
    1. Model的更新是通过观察者模式告知View的==>Pub/Sub或者是触发Events

(其实组件分层也是这个意思吧。木偶组件与受控组件
P.S. 观察者通知更新的好处,(一般观察者涉及到多个观察者,一个数据源)

  • 不同的MVC三角关系可能会有共同的Model,一个MVC三角中的Controller操作了Model以后,两个MVC三角的View都会接受到通知,然后更新自己。从而保证了依赖同一块model的不同view显示数据的实时性和准确性

mvc优缺点分析:
优点:

  1. 把业务逻辑和展示逻辑分离,模块化程度高。且当应用逻辑需要变更的时候,不需要变更业务逻辑和展示逻辑,只需要Controller换成另外一个Controller就行了(Swappable Controller)。
  2. 观察者模式可以做到多视图同时更新

缺点:

  1. Controller测试困难。因为视图同步操作是由View自己执行,而View只能在有UI的环境下运行。在没有UI环境下对Controller进行单元测试的时候,应用逻辑正确性是无法验证的:Model更新的时候,无法对View的更新操作进行断言。
  2. View无法组件化。View是强依赖特定的Model的,如果需要把这个View抽出来作为一个另外一个应用程序可复用的组件就困难了。因为不同程序的的Domain Model是不一样的

随着业务越来越复杂,视图交互越复杂,导致Controller越来越臃肿,负重前行
一个小小的mvc demo
(jsp的MVC是啥呢,好像和这个又有点不一样呢?

经典的MVC模式只是解决客户端图形界面应用程序的问题,而对服务端无效。服务端的MVC模式又自己特定的名字:MVC Model 2,或者叫JSP Model 2,或者直接就是Model 2

image.png

Model 2模式最早在1998年应用在JSP应用程序当中,JSP Model 1应用管理的混乱诱发了JSP参考了客户端MVC模式,催生了Model 2。
image.png
后来这种模式几乎被应用在所有语言的Web开发框架当中。PHP的ThinkPHP,Python的Dijango、Flask,NodeJS的Express,Ruby的RoR,基本都采纳了这种模式。平常所讲的MVC基本是这种服务端的MVC。

MVP

  1. Passive View(view 是木偶组件
  2. Supervising Controller

MVP模式是MVC模式的改良
image.png

关键点:

  1. View不再负责同步的逻辑,而是由Presenter负责。Presenter中既有应用程序逻辑也有同步逻辑。
  2. View需要提供操作界面的接口给Presenter进行调用。(关键)

(这个就有点象 插件机制了 view提供接口给presenter,view把change接口给插件机制了)
MVC中,Controller是不能操作View的,View也没有提供相应的接口
而在MVP当中,Presenter可以操作View,View需要提供一组对界面操作的接口给Presenter进行调用

Model仍然通过事件广播自己的变更,但由Presenter监听而不是View。

优缺点:
优点:

  1. 便于测试。Presenter对View是通过接口进行,在对Presenter进行不依赖UI环境的单元测试的时候。可以通过Mock一个View对象,这个对象只需要实现了View的接口即可。然后依赖注入到Presenter中,单元测试的时候就可以完整的测试Presenter应用逻辑的正确性。这里根据上面的例子给出了Presenter的单元测试样例
  2. View可以进行组件化。在MVP当中,View不依赖Model。这样就可以让View从特定的业务场景中脱离出来,可以说View可以做到对业务完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做到高度可复用的View组件。(此时view组件被解释为 底层组件,无关业务的)

缺点:

  1. Presenter中除了应用逻辑以外,还有大量的View->Model,Model->View的手动同步逻辑,造成Presenter比较笨重,维护起来会比较困难。

MVVM

MVVM代表的是Model-View-ViewModel.
ViewModel即”Model of View”,视图的模型,包含了领域模型(Domain Model)和视图的状态(State)

界面所提供的信息可能不仅仅包含应用程序的领域模型。还可能包含一些领域模型不包含的视图状态
电子表格程序上需要显示当前排序的状态是顺序的还是逆序的,而这是Domain Model所不包含的,但也是需要显示的信息 所以在viewmodel里不仅有 list的table数据抽象,还有style的抽象?可以这样理解吗 视图模型就是将视图有关的所有数据的抽象表示了,而不单单是后端数据的 树状数据等

image.png

只要确定好了数据流,那么下一步核心实现就是data-bind 引擎
优缺点:
优点:

  1. 提高可维护性。解决了MVP大量的手动View和Model同步的问题,提供双向绑定机制。提高了代码的可维护性。
  2. 简化测试。因为同步逻辑是交由Binder做的,View跟着Model同时变更,所以只需要保证Model的正确性,View就正确。大大减少了对View同步更新的测试。

缺点:

  1. 过于简单的图形界面不适用,或说牛刀杀鸡。
  2. 对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高。
    1. 是否又涉及到 大型应用怎么划分状态管理的问题了?分为 事件驱动型 和 数据驱动型
    2. 大型应用难的本质就是在于状态管理,这也是为啥 徐叔 这几年都在钻研于此的原因吧
  3. 数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的。

图:

扩展阅读