MVC VS. MVP VS. MVVM
了解MVVM模式之前,我们先来简单了解一下从MVC到MVVM的变迁。这个变迁是耦合从紧到松的变迁,是对依赖处理的进化,是应对变化技术的成熟。
MVC
MVC全名是Model View Controller, 是模型(model)-视图(view)-控制器(controller)的缩写,它用一种将业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。将系统进行MVC分层的核心思路就是分离组件,降低组件耦合性,组件独立演化。
MVC模式可以使用下面这幅图来描述各个部分的作用以及与其他组件的交互过程:
MVC模式的优点很明显,那就是耦合性低,重用性高,应对每个组件的变化性好,便于开发,测试与维护。但是MVC模式也还是有缺点的,给系统带来的额外复杂性自然不必说了,此外,MVC三个组件的定义存在一定的模糊性,这样就衍生了很多的比如主动MVC,被动MVC等实施方案,每种方案中MVC三大组件的功能都不太一样,比如有的把业务逻辑放到Model部分,Controller只不过是把用户输入转换一下,直接传给Model来处理,Model是整个系统的核心部分,上面这幅图就是这样的,还有的方案把业务逻辑直接放到了Controller中,Model只负责处理数据。而且在不同的方案中,要么View与Controller耦合过于紧密,要么View访问Model的时候比较低效,要么Model由于要与View直接打交道,导致了Model与View直接耦合在了一起,这却恰恰违背了MVC组件分层的本意。
MVP
MVP的全称为Model-View-Presenter,Model提供数据,View负责显示,Presenter负责逻辑的处理。MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过Controller。
MVP模式可以使用下面这幅图来描述各个部分的作用以及与其他组件的交互过程:
在MVC里,我们谈到它的缺点主要有两个:
一个是MVC三大组件的定义比较模糊。这个在MVP中就相对明确一些了:Model只负责处理最终数据;View就是很薄的一层,只显示数据,通常认为,View只应该有简单的Set/Get的方法,View只负责用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接访问Model;所有业务逻辑都由Presenter处理,而且,Presenter与具体的View和Model是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View或者Model具体实现的时候可以保持Presenter的不变,这样就实现了业务逻辑的重用。
另一个是View与Model的紧密耦合。在MVC中,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
在现实中,MVP的实现会根据View的充、贫血而有一些不同,一部分倾向于在View中放置简单的逻辑,在Presenter放置复杂的逻辑;另一部分倾向于在presenter中放置全部的逻辑。这两种分别被称为:Passive View和Superivising Controller。
在Passive View中,为了减少UI组件的行为,使用Controller不仅控制用户事件的响应,而且将结果更新到View上。可以集中测试Controller,减小View出问题的风险。
在Superivising Controller中的Controller既处理用户输入的响应,又操作View处理View的复杂逻辑。
MVP解决了MVC的一些问题,其实现在说到MVC,通常指的也就是MVP。但是MVP也是不完美的,由于Presenter可以反作用于View,这样View的渲染有可能就放在了Presenter中,所以View和Presenter的交互会过于频繁。如果Presenter过多地渲染了View,往往会使得它与特定的View的联系过于紧密。一旦View需要变更,那么Presenter也需要变更了。
MVVM
MVVM全称Model-View-ViewModel,Model提供数据,View负责显示,这个还和MVP一样,这个模式的重点就是ViewModel的部分,它通过双向绑定(松耦合)解决了MVP中Presenter与View联系比较紧密的问题。
MVVM模式可以使用下面这幅图来描述各个部分的作用以及与其他组件的交互过程:
从图中我们可以看到MVVM与MVP最大的不同就在于View与ViewModel交互的时候使用了松耦合的双向绑定,而不是像View与Presenter那样直接交互。ViewModel作为View的数据映射,通常View上有什么属性,ViewModel上也会存在相应的一个属性,这两个属性通过事件实现了双向的绑定,常见的MVVM框架都替我们完成了这样的绑定过程。
MVVM最初是微软在WPF中实现的模式,随之在Web开发中也开始了MVVM风潮,这里介绍的3个MVVM框架就是我认为比较典型的几个。
微软的前端框架knockoutjs
这是一个独立的前端MVVM框架,也是最早的前端MVVM框架,它完成了页面的数据与界面之间的双向绑定,至于真正这些数据是通过何种手段(比如Ajax)获取到的,它并不关心。这是一个只关注前端逻辑与界面解耦的纯前端类库,理论上可以搭配任何的后台技术,来完成整个网站的建设。这是我第一个学习的MVVM框架,使用它给我的感觉是相当良好:绑定好了自动双向更新是多么酷的特性啊。
下面是比较火热的几个学习教程:
http://knockoutjs.com/
http://www.cnblogs.com/TomXu/archive/2011/11/21/2257154.html
http://www.cnblogs.com/lori/p/3552571.html
谷歌的全套服务angularjs
这是一个比较庞大,但是也无比强大的前端MVVM类库,天生对RESTful API的良好支持,双向绑定的优良特性,专业的HTML模板扩展支持,全面的测试框架,与Bootstrap,Nodejs的完美融合,再加上Google的金字招牌,你可以拒绝么?
下面是比较火热的教程:
https://angularjs.org/
http://www.ituring.com.cn/minibook/303
http://www.iteye.com/news/28651-AngularJS-Google-resource
http://woxx.sinaapp.com/
http://www.angularjs.cn/tag/AngularJS
最迷你的MVVM框架avalon
这确实是最mini的MVVM框架,与Angularjs不一样,它侧重数据结构的设计,提倡简单的算法,它是在吸收上面两个类库的基础上发展起来的,而且符合国情,支持IE6,难道不值得期待?
下面是比较好的教程:
http://rubylouvre.github.io/mvvm/
http://limodou.github.io/avalon-learning/zh_CN/index.html
http://www.cnblogs.com/rubylouvre/p/3181291.html
http://www.oschina.net/p/avalon
http://www.iteye.com/topic/1130359
http://www.tuicool.com/articles/NrMrIn
最后附送一个有意思的网站:http://todomvc.com/,自己研究一下吧。
JavaScript大杂烩18 - Web开发的MVVM模式