前言

在前端技术的快速发展过程中,MVC(模型-视图-控制器)、MVP(模型-视图-表示器)和MVVM(模型-视图-视图模型)也得到了很多使用。然而,这三种框架模式非常相似,不易分清,易于混淆。本文重在讲述它们的概念和应用场景及它们之间的细微差别,使我们更好的理解和使用这三种框架模式。

1.MVC

MVC全名是Model View Controller,是模型(Model)-视图(View)-控制器(Controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。它强制将业务数据(Model)与用户界面(View)隔离,使用控制器(Controller)来管理逻辑和用户输入。其模式图为:

MVC框架模式其三个部分的含义为:

  • Model:负责在数据库中存取数据,是应用程序中用于处理应用程序数据逻辑的部分。Model不涉及用户界面,也不涉及表示层,而是负责提供应用程序需要的特殊格式的数据。
  • View:描绘的是Model的当前状态,用来显示数据,是应用程序中处理数据显示的部分。View是Model的可视化表示,表示当前状态的筛选视图。用户可以与View交互,包括读取和编辑Model,而更新Model的工作实际由Controller完成。
  • Controller:通常控制器负责从View读取数据,控制用户输入,并向Model发送数据,是应用程序中处理用户交互的部分。Controller是Model和View之间的中介,当用户操作View时,它通常负责更新Model。

MVC的优势

  • 整体维护更容易。数据中心是否改变,什么时候需要更新应用程序这点很清楚。
  • 解耦Model和View,意味着它能够更直接地编写业务逻辑的单元测试。
  • 在整个程序应用中,减少了底层Model和Controller代码的重复,更加高效,易于维护。
  • 由于表示和逻辑的分离,更加易于分工协作,可以让负责核心逻辑的开发人员和负责用户界面的开发人员同时工作。

2.MVP

MVP(模型-视图-表示器)是MVC框架模式的一种衍生模式,专注于改进表示逻辑。MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Presenter负责逻辑的处理。在MVP中,当Model变化时,监控Model和更新View,Presenter将Model有效地绑定至View。其模式图为:

MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。

在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用!

MVP最常用于企业级应用中,因为这类项目需要尽可能多地重用表示逻辑。具有非常复杂的View和大量用户交互的应用程序可能发现MVC并不能完全符合要求,因为这需要更多的控制器。在MVP中,这些复杂的逻辑可言封装在一个表示器中,可以极大的简化维护工作。

MVP的优势:

  • 模型与视图完全分离,我们可以修改视图而不影响模型。
  • 可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部。
  • 我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
  • 如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。

3.MVVM

MVVM(模型-视图-视图模型)是一种基于MVC和MVP的架构模式,它试图更清晰地将用户界面开发从应用程序的业务逻辑与行为中分离。MVVM的全称为Model-View-ViewModel,其中可以将ViewModel看成一个专门的Controller,充当数据转换器,它将Model信息转变成View信息,还将命令从View传递到Model。为此,很多这种模式的实现都要利用声明式数据绑定来实现将View工作从其他层分离。其模式图为:

View与ViewModel:View与ViewModel之间经过数据绑定和事件进行通信,ViewModel不只暴露Model属性,还会访问其他方法和验证类的特性。View处理自己的用户界面事件,必要时将它们映射到ViewModel。Model和ViewModel上的属性通过双向数据绑定进行同步和更新。数据触发器也可以使我们进一步地对Model属性的状态变化做出反应。

ViewModel与Model:ViewModel似乎完全负责MVVM中的Model,ViewModel可以为了数据绑定而暴露Model或Model属性,也可以包含接口,用于获取和操作在View中暴露的属性。

MVVM优势:

  • 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • MVVM使View抽象化,让很多view重用这段视图逻辑,减少代码背后所需的业务逻辑。
  • 独立开发,使得UI和为UI提供驱动的行为模块的并行开发变得更容易。
  • ViewModel在单元测试中的使用比在事件驱动代码中的使用更加容易。
  • 不需要考虑UI自动化和交互就可以测试ViewModel。

缺点:

  • MVVM不适合简单UI项目。
  • 数据绑定是声明式的,虽然使用方便,但比命令式代码更难调试,在命令式代码中,我们打断点就好了。
  • 大型应用程序中的数据绑定将会产生大量的标记。
  • 在较大型应用程序中,预先设计大量的ViewModel可能更加困难。

总结

MVP和MVVM都是MVC衍生出来的,它们之间的不同在于每一层对其他层的依赖,以及它们是如何紧密相互绑定的。

  • 在MVC中,View了解Controller,Controller了解Model,View也可以直接访问Model。由于View直接访问Model,缺少一定的控制,可能会带来安全性和性能成本,这由程序的复杂性决定。MVVM试图解决这方面的问题。
  • 在MVP中,Controller被Presenter所替代。Presenter位于View和Model之间,监听二者事件,协调它们之间的行动。与MVVM不同,MVP没有将View绑定至ViewModel的机制,这就需要依赖每个View来实现用于让Presenter与View进行交互的接口。
  • 在MVVM中,Model可以特定于View,可以包含状态和逻辑信息,无需向View暴露整个Model。与MVP中的Presenter不同,引用View时不需要ViewModel。View可以绑定到ViewModel上的属性,而属性将Model包含的数据提供给View展示。View的抽象减少了背后所需的代码逻辑。然而,View与ViewModel之间需要进行解释,会有性能消耗。

MVC、MVP、MVVM这三种框架模式在不同的业务上有不同的适用性,只要能满足业务需要就行。

JavaScript之MV*模式的更多相关文章

  1. 界面之下:还原真实的 MV* 模式

    界面之下:还原真实的MV*模式 作者:戴嘉华 转载请注明出处并保留原文链接( https://github.com/livoras/blog/issues/11 )和作者信息. 目录: 前言 MVC ...

  2. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  3. MV*模式的个人理解

    MV*模式主要解决的问题就是 View代码难以维护的问题. MV*模式将View中的逻辑分离出去,形成一个弱逻辑的易于维护的视图. MV*中的*是Model和View的桥梁,负责保持Model和Vie ...

  4. JavaScript高级---门面模式设计

    门面模式 两个作用: 1.简化类的接口 2.消除类与使用它的客户代码之间的耦合 门面模式常常是开发人员最亲密的朋友.它几乎是所有javascript库的核心原则 门面模式的目的是为了让开发人员用更简单 ...

  5. JavaScript高级---组合模式设计

    一.设计模式 javascript里面给我们提供了很多种设计模式: 工厂.桥.组合.门面.适配器.装饰者.享元.代理.观察者.命令.责任链 在前面我们实现了工厂模式和桥模式 工厂模式 : 核心:为了生 ...

  6. JavaScript高级---桥模式设计

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...

  7. JavaScript实现策略模式

    在开篇之前先分享今天看到的一句关于设计模式的话:将不变的部分和变化的部分隔开是每个设计模式的主题 请大家自行感受这句话的精髓所在,并且思考学习设计模式究竟能给我们编程带来什么样的东西,欢迎大家在文章下 ...

  8. javascript闭包(Module模式)的用途和高级使用方式

    javascript闭包(Module模式)的用途和高级使用方式 javascript闭包的用途:1. 匿名自执行函数:或者可以理解为,避免污染全局变量2. 缓存:源于闭包的核心特性便是保存状态,应用 ...

  9. 【整理总结】代码沉淀 - Caliburn.Micro - MV*模式短小精悍的框架

    Caliburn.Micro - Xaml made easy. web: https://github.com/Caliburn-Micro/Caliburn.Microdocument: http ...

随机推荐

  1. C 语法中static 和inline联合使用

    最近在学习阶段,翻阅代码.发现有一个用法比较让我奇怪,就上网查了一下 ? 1 static inline void somefunction(void); 这里是举例说明,这行代码是放在.h文件中的. ...

  2. WEB入门.七 CSS布局模型

    学习内容 标准文档流 流动模型(flow model) 浮动模型(float model) CSS基本布局 能力目标 理解标准文档流 使用流动模型实现页面布局 使用浮动模型实现页面布局 掌握常用CSS ...

  3. 解题:ZJOI 2013 K大数查询

    题面 树套树,权值线段树套序列线段树,每次在在权值线段树上的每棵子树上做区间加,查询的时候左右子树二分 本来想两个都动态开点的,这样能体现树套树在线的优越性.但是常数太大惹,所以外层直接固定建树了QA ...

  4. 一些程序OEP入口特征

    声明: 1.本文中使用的例子来源于吾爱破解的官方教程第一课中的无壳例子,本人利用空闲时间挨个进行查看并截图纪录下来 2.欢迎补充讨论 一些程序OEP入口特征 一.       AMS程序 1.载入PE ...

  5. 「Vue」自定义指令

    #全局自定义指令1.使用Vue.directive()定义全局的指令 v-focus2.参数1 指令的名称,在定义的时候,指令的名称前面不需要加v-前缀3.但是在调用的时候必须在指令名称前 加上v-前 ...

  6. vue中import xxx from 和 import {xxx} from的区别

    1.import xxx from import FunName from ‘../xxx’ 对应js中的引用: export defualt function FunName() { return ...

  7. 简便开发插件 -- lombok

    lombok是一款可以精减java代码.提升开发人员生产效率的辅助工具,可以利用注解在编译期自动生成setter/getter/toString()/constructor代码. 彻底将开发人员从繁琐 ...

  8. angularJS__v1.5.6点击同一个菜单刷新

    针对angularjs的1.0版本,点击菜单不刷新问题,只需在配置路由时,路由路径添加“/”,如,点击 标签时,就会刷新,

  9. Diabetic Retinopathy Winner's Interview: 1st place, Ben Graham

    Diabetic Retinopathy Winner's Interview: 1st place, Ben Graham Ben Graham finished at the top of the ...

  10. [转载]Require.js Example – Setup Time 2 Minutes

    http://www.sitepoint.com/require-js-setup-time-2-minutes/ Setup Require.js in just 2 minutes. or dow ...