前言

在前端技术的快速发展过程中,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. 【bug】Could not find method compile() 解决

     集成第三方库出现 Error:Could not find method compile() for arguments [com.android.support:design:23.4.0] on ...

  2. ot

    https://blog.csdn.net/notice520/article/details/8135600 | android中的跨进程通信的实现(一)——远程调用过程和aidl - CSDN博客 ...

  3. 2016-2017 National Taiwan University World Final Team Selection Contest (Codeforces Gym) 部分题解

      D 考虑每个点被删除时其他点对它的贡献,然后发现要求出距离为1~k的点对有多少个. 树分治+FFT.分治时把所有点放一起做一遍FFT,然后减去把每棵子树单独做FFT求出来的值. 复杂度$nlog^ ...

  4. bzoj 4028 : [HEOI2015]公约数数列

    之前看了好几次都没什么思路,今天下定决心把这题切了. 观察到$0-x$的gcd最多变化log次,因为它每次变化一定至少要去掉一个质因子,所以我们可以枚举gcd. 因为数据范围比较小,所以想到了分块. ...

  5. Python 爬虫入门(一)

    毕设是做爬虫相关的,本来想的是用java写,也写了几个爬虫,其中一个是爬网易云音乐的用户信息,爬了大概100多万,效果不是太满意.之前听说Python这方面比较强,就想用Python试试,之前也没用过 ...

  6. Chapter2(变量和基础类型)--C++Prime笔记

    数据类型选择的准则: ①当明确知晓数值不可能为负时,选用无符号类型. ②使用int执行整数运算.在实际应用中,short常常显得太小而long一般和int有一样的尺寸.如果运算范围超过int的表示范围 ...

  7. python——type()、metaclass元类和精简ORM框架

    1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...

  8. android中倒计时控件CountDownTimer分析

    android中倒计时控件CountDownTimer分析 1 示例代码 new CountDownTimer(10000, 1000) { public void onTick(long milli ...

  9. 介绍——基于类的视图(class-based view)

    ​刚开始的时候,django只有基于函数的视图(Function-based views).为了解决开发视图中繁杂的重复代码,基于函数的通用视图( Class-based generic views) ...

  10. css3-自定义字体

    参考链接http://www.w3cplus.com/content/css3-font-face 出处W3CPLUS css3-自定义字体   @font-face @font-face是CSS3中 ...