主动MVC
MVC源自桌面应用程序,它的理论思想对应的是主动MVC, 这里的主动的意思是, Model会主动通知View更新。
Model
用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。
模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。
View
视图层负责数据的展示。
在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里订阅Model的事件。
Controller
控制器是M和V之间的连接器,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。
被动MVC
下图是被动MVC中的流程,和主动MVC不同之处是, View没有订阅Model数据变化的事件,等待Model来通知需要根据新的数据来更新View。在被动MVC中,Controller负责通知View, 有数据变化,需要更新视图。
被动MVC 与主动MVC的区别
1、模型对视图和控制器一无所知,它仅仅是被它们使用
2、控制器使用视图,并通知它更新数据显示
3、视图仅仅是在控制器通知它去模型取数据的时候它才这么做(视图并不会订阅或监视模型的更新)
Web应用中的MVC框架
Web中的MVC框架都是被动MVC模式,因为http是基于请求和响应方式协同工作的,因此当服务器端的model(数据)发生变化时,它不会立即更新客户端的view,只有客户端重新请求或刷新页面时才更新.
下图是典型的MVC框架中的MVC一个请求流程。
MVC优点
由于MVC很好的分离了视图层和业务层,所以它具有以下优点
- 耦合性低
- 开发速度快
- 可维护性高
- 没有控件的概念,对html没有封装,易于理解
- 和其它平台(java, php)等更加相似。便于人才获取
MVC使用的误区
把Model理解成实体类(Entity)
在MVC中Model应该包含2部分功能,一部分是处理业务逻辑,一部分是提供View显示的数据。
它应该是业务逻辑真正的实现层。所以Model的实际上是Business Model(业务模型)。而Controller仅仅起一个“桥梁”作用,它负责把View的请求转发给Model,再负责把Model处理结束的消息通知View。Controller是用来解耦View和Model的,具体一点说,就是为了让UI与逻辑分离(界面与代码分离)。
Techopedia explains Model (MVC)
The Model is the part of MVC which implements the domain logic. In simple terms, this logic is used to handle the data passed between the database and the user interface (UI).
The Model is known as domain object or domain entity.
The domain objects are stored under the Models folder in ASP.NET. The domain model represents the application perspective for the data to be handled whereas a view model is required to produce the engine that generates the View.
This definition was written in the context of ASP.NET.
把业务逻辑全部放在Controller端
MVC中的控制器,内里封装了通讯,容易变成大而全 的高度耦合的集中器。
- 控制器中写业务代码
- 写代码的人“修炼”不够。不能理解高内聚低耦合的OO思想主旨
- 项目负责人放任自流。导致代码混乱。
-
控制器变得依赖信息数据中心或数据库,对象将间接地通过控制器的action耦合在一起
- 引入IOC容器
MVP
MVP模式中的V代表的是一个接口,一个将UI界面提炼而抽象出来的接口。接口意味着任何实现了该接口的界面,都能够复用已有的Presenter和Model代码。真正意义上的隔离View的细节和复杂性的模式。
MVP具有很多的变体,其中最为常用的一种变体成为Passive View(被动视图)。对于Passive View,Model、View和Presenter之间的关系如下图所示。View和Modell之间不能直接交互,View通过Presenter与Model打交道。Presenter接受View的UI请求,完成简单的UI处理逻辑,并调用Model进行业务处理,并调用View将相应的结果反映出来。View直接依赖Presenter,但是Presenter间接依赖View,它直接依赖的是View实现的接口。
Passive View,顾名思义,View是被动的。那么主动是谁呢?答案是Presenter。
- Presenter是整个MVP体系的控制中心,而不是单纯的处理View请求的人;
- View仅仅是用户交互请求的汇报者,对于响应用户交互相关的逻辑和流程,View不参与决策,真正的决策者是Presenter;
- View向Presenter发送用户交互请求应该采用这样的口吻:“我现在将用户交互请求发送给你,你看着办,需要我的时候我会协助你”,不应该是这样:“我现在处理用户交互请求了,我知道该怎么办,但是我需要你的支持,因为实现业务逻辑的Model只信任你”;
- 对于绑定到View上的数据,不应该是View从Presenter上“拉”回来的,应该是Presenter主动“推”给View的;
- View尽可能不维护数据状态,因为其本身仅仅实现单纯的、独立的UI操作;Presenter才是整个体系的协调者,它根据处理用于交互的逻辑给View和Model安排工作。
在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在Presenter里实现。而且,Presenter与具体的 View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以保持Presenter的不变,即重用! 不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试 —— 而不需要使用自动化的测试工具。 我们甚至可以在Model和View都没有完成时候,就可以通过编写Mock Object(即实现了Model和View的接口,但没有具体的内容的)来测试Presenter的逻辑。
MVP的优势
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presener用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户界面来测试这些逻辑(单元测试)
MVVM
MVVM模式中,一个ViewModel和一个View匹配,它没有MVP中的IView接口,而是完全的和View绑定,所有View中的修改变化,都会自动更新到ViewModel中,同时ViewModel的任何变化也会自动同步到View上显示。
这种自动同步之所以能够的原因是ViewModel中的属性都实现了observable这样的接口,也就是说当使用属性的set的方法,都会同时触发属性修改的事件,使绑定的UI自动刷新。(在WPF中,这个observable接口是 INotifyPropertyChanged; 在knockoutjs中,是通过函数ko.observable() 和ko.observrableCollection()来实现的)
所以MVVM比MVP更升级一步,在MVP中,V是接口IView, 解决对于界面UI的耦合; 而MVVM干脆直接使用ViewModel和UI无缝结合, ViewModel直接就能代表UI. 但是MVVM做到这点是要依赖具体的平台和技术实现的,比如WPF和knockoutjs, 这也就是为什么ViewModel不需要实现接口的原因,因为对于具体平台和技术的依赖,本质上使用MVVM模式就是不能替换UI的使用平台的.
MVVM的提出源于WPF,主要是用于分离应用界面层和业务逻辑层。WPF/Siverlight是基于数据驱动开发的。
在MVC和MVP模式中, View层都具有很多代码逻辑, 开发View层的是程序员, 虽然UI/UE团队会做很多工作, 但这个层的"实现者"仍然是程序员。
而在WPF开发中程序员对View层的展现显得力不从心了,美工虽然很擅长, 但他会说"可惜我不会程序".于是, 我们需要一种方式将View层的代码逻辑抽取出来,并View层很纯粹以便完全让美工去打造它.相应地, 需要将View层的相应逻辑抽取到一个代码层上,以便让程序员专注在这里。
MVC, MVP和MVVM模式使用场景总结
由于在winform中无法像WPF一样,支持数据和界面的双向绑定以及事件的监控,所以,在winform中MVP是最佳选择。
WPF和html界面中使用Knockout,实现了observable, 所以使用MVVM.(应该说WPF就是为使用MVVM设计的)
在web应用中,由于http是基于请求和响应方式协同工作的, 无法一直保持连接状态,所以无法达到MVP中Presenter之间的消息传递和MVVM中的ViewModel和界面之间的绑定, 所以MVC是最佳的选择。
MVC的包容度比MVVM和MVP要来的高,在MVC的V层,可以再进一步的包含MVVM或MVP的实作,而C层也可以使用MVP (V是输出的资料)来进一步切割资料的流动与输出,M层则可以类似MVVM的架构,当V (元件)有资料的异动时,VM即可自动侦测到并更新Model (资料库)。
MVC中引入MVVM的意义
前端工程师们与程序开发人员们实现了真正的分离,当然,为了减少重复代码量,前端人员有必要了解一个数据库结构。
eg:augularjs