设计模式:MVC和MVP和MVVM

软件架构 / 设计模式

MVC

  • View 传送指令到 Controller
  • Controller 完成业务逻辑后,要求 Model 改变状态
  • Model 将新的数据发送到 View,用户得到反馈
    以上均为单项通信
  1. 主动MVC
    用户向 View 发送指令(DOM 事件),再由 View 直接要求 Model 改变状态。
    model :在MVC中Model应该包含2部分功能,一部分是处理业务逻辑,一部分是提供View显示的数据。
    模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。
    view:为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里订阅Model的事件。
    Controller:控制器是M和V之间的连接器,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。
  2. 被动MVC
    View没有订阅Model数据变化的事件,等待Model来通知需要根据新的数据来更新View.在被动MVC中,Controller负责通知View, 有数据变化,需要更新视图。
  3. 被动MVC 中,与 主动MVC 的区别在于:

    • M模型对V视图和C控制器一无所知,它仅仅是被它们使用
    • 控制器使用视图,并通知它更新数据显示
    • 视图仅仅是在控制器通知它去模型取数据的时候它才这么做(视图并不会订阅或监视模型的更新)

      Web中的MVC框架都是被动MVC模式,因为web应用中, 由于http是基于请求和响应方式协同工作的,因此当服务器端的model(数据)发生变化时,它不会立即更新客户端的view,只有客户端重新请求或刷新页面时才更新.

  4. 总结
    Model在MVC架构中应该是业务逻辑真正的实现层。所以Model的实际上是Business Model(业务模型)。
    Controller仅仅起一个“桥梁”作用,它负责把View的请求转发给Model,再负责把Model处理结束的消息通知View。
    Controller是用来解耦View和Model的,具体一点说,就是为了让UI与逻辑分离(界面与代码分离)。
    而缺点是,由于MVC的设计思想是从Model出发,而没有考虑到View端的复杂性,这样导致的问题是Model难以符合复杂多变的View端变化。model和view的耦合度太高,每当出现不同需求的view时,都要对model进行相应的修改。

    MVP

    MVP是Modal-View-Presenter的缩写。

    • 各部分之间的通信,都是双向的。
    • View 与 Model 不发生联系,都通过 Presenter 传递。
    • View 非常薄,不部署任何业务逻辑,称为”被动视图”(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

      在其它模式中V都代表的是UI界面, 是一个html页面,XAML文件或者winform界面。但是在MVP模式中的V代表的是一个接口,一个将UI界面提炼而抽象出来的接口。Presenter与具体的 View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用
      (比如,model指数据库,view视图中的输入框在presenter中抽象为属性,而presenter是逻辑代码,调用接口以及提供set/get函数等事件处理)

      MVVM

      MVVM是Model-View-ViewModel的缩写。
      在说MVVM是什么之前,我们先来看廖雪峰老师的一个例子,或许可以更好理解它。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <!-- HTML -->
      <p>Hello, <span id="name">Bart</span>!</p>
      <p>You are <span id="age">12</span>.</p>
      <!-- jQuery -->
      'use strict';
      ----
      var name = 'Homer';
      var age = 51;
      $('#name').text(name);
      $('#age').text(age);
      ----
      // 执行代码并观察页面变化

在上述代码中,jQuery通过操作DOM节点来修改数据。
而使用MVVM模式设计又是怎样的呢?我们来看下面这段代码。

1
2
3
4
5
6
7
8
9
<!-- 这次先着眼于数据存储,我们用一个对象实现 -->
var person = {
name: 'Bart',
age: 12
};
<!-- 当我们需要修改数据的,只需要修改该对象而不去操作DOM结点 -->
person.name = 'Homer';
person.age = 51;

从上述代码可以看出,MVVM模式把Model层变成纯JavaScript操作,并只需着眼于业务逻辑,而减少直接操作view层结构。关注Model的变化,让ViewModel去自动更新V层的状态,从而把开发者从操作DOM的繁琐步骤中解脱出来,实现M层和V层最大的分离,即View与Model通过ViewModel实现双向绑定。而在MVC模式中,当 Model 频繁发生变化,开发者需要主动更新到View ;当用户的操作导致 Model 发生变化,开发者同样需要将变化的数据同步到Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。

在MVVM架构下,

  • View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互
  • Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
  • ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

看到这里是不是自然想到了vue.js的数据双向绑定呢~vue.js虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。最切身体会的一点的就是,写单页面应用的时候,再也不需要在js里面写那一串串超讨厌的获取DOM节点的代码并操作它,vue.js的数据双向绑定的好处就是你只需要专注于某个对象,并只需要修改该对象的值,而相应的视图就会进行更新
下面就是一个简单的vue实例~

1
2
3
4
5
6
7
8
9
10
<!-- html -->
<div id="el">{{message}}</div>
<!-- js -->
new Vue({
el:'#el',
data{
message:'初始化数据,或在methods中使用this.message修改数据'
},
methods:{}
})

这里是vue spa应用的一个简单的小组件~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
{{message}}
</div>
</template>
<script>
export default {
data(){
return{
message:'初始化数据,或在methods中使用this.message修改数据'
}
},
methods:{}
}
</script>

嘻嘻嘻 是不是觉得身心舒畅很多~