到底什么是MVC?

标签: 程序设计 MVC | 发表时间:2013-10-12 02:58 | 作者:标点符
出处:http://www.biaodianfu.com

先前整理过一篇文章,讲的是 如何使用Php搭建Mvc框架,前几天看了一些文章,对MVC又有了新的认识,具体整理如下:

一、Classic MVC

MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。最早由Trygve Reenskaug在1978年提出,并应用在 Smalltalk系统中。

Classic Mvc模式:

  • Model:封装领域数据及逻辑。用于管理应用程序域的行为和数据,并响应为获取其状态信息(通常来自视图)而发出的请求,还会响应更改状态的指令(通常来自控制器)。
  • View:查询领域数据并展现给用户。用于管理信息的显示。
  • Conctroller:截获用户请求并改变领域数据。用于解释用户的鼠标和键盘输入,以通知模型和/或视图进行相应的更改。

MVC-Process

从依赖关系看,Model不依赖View和Controller,而View和Controller依赖Model。

Classic MVC关注两个分离:

  • 从Model中分离View
  • 从View中分离Controller

从Model中分离View,主要基于以下几点考虑:

  1. 不同的关注点:Model关注内在的不可视的逻辑,而View关注外在的可视的逻辑。
  2. 多种表现形式:同一个Model往往需要多种View表现形式。
  3. 提高可测试性:相对Model而言,View是不容易测试的。

Desktop软件的时代,View和Controller往往是一一对应的关系,所以常常把他们合并成为UI,事实上,当时多数UI框架都没有实现从View中分离Controller。后来随着Web的兴起,这种分离(模板技术)才开始流行起来。

本质上Classic MVC的结构如下图所示,之所以说本质上,是因为View和Controller其实是彼此关联的,但这种关联和稍后提到的MVP完全不同,更像是一种框架的副产品,为了避免引起混淆,这里省略了它们,具体参阅: How to use Model-View-Controller (MVC)

classic_mvc

Controller截获用户通过鼠标或键盘发出的请求,然后改变Model的状态,Model通过 Observer Synchronization(观察者模式)通知View自己的状态发生了变化。View查询Model展现数据。

Classic MVC并不完美,不适用于复杂的逻辑。举个例子:用户通过鼠标拖动滚动条来调整音量大小,如果音量大于某个数值,背景色变红以示提醒。当使用Classic MVC的时候,如何处理背景色变红的逻辑呢?

有两个选择:

  1. Model触发一个特殊事件,View收到后完成相关逻辑的处理。但我们前面说过,从依赖关系上看,Model应该完全无视View的存在。
  2. 在View中判断音量临界值,达到后完成相关逻辑的处理。但我们前面说过,View是不容易测试的,应该尽可能减少逻辑处理。

Classic MVC并不完美,不适用于复杂的逻辑。举个例子:用户通过鼠标拖动滚动条来调整音量大小,如果音量大于某个数值,背景色变红以示提醒。当使用Classic MVC的时候,如何处理背景色变红的逻辑呢?有两个选择:

  1. Model触发一个特殊事件,View收到后完成相关逻辑的处理。但我们前面说过,从依赖关系上看,Model应该完全无视View的存在。
  2. 在View中判断音量临界值,达到后完成相关逻辑的处理。但我们前面说过,View是不容易测试的,应该尽可能减少逻辑处理。

上述只是提出了Classic MVC的一些缺陷,那到底如何解决呢?请继续关注下文~

二、Application Model MVC

大概上世纪八十年代,ParcPlace从Xerox Parc划分出来,负责Smalltalk的研发工作,为了适应更复杂的逻辑,开发了Classic MVC的改进版,也就是Application Model MVC,在原有架构基础上引入了Application Model,如下图所示:

application_model_mvc

Application Model在Model和View、Controller之间扮演着一个中继者的角色。接着看前面的例子,既然Model和View都不适合放背景色变红的逻辑,那么我们可以尝试把相关逻辑放在Application Model中实现,当用户通过鼠标调整音量大小时,Model触发一个普通事件,Application Model拦截到这个事件,判断音量是否大于临界值,如果是就触发一个特殊事件,View收到后完成相关逻辑的处理。

Application Model MVC虽然看似解决了复杂逻辑的问题,但它仍然存在硬伤:

  1. 随着以微软视窗为主的图形化操作系统的兴起,操作系统本身提供了一套原生的View接口,用来截获用户通过鼠标或键盘发出的请求,结果让Controller显得多余了。
  2. 由于在Application Model MVC中,View的渲染只能通过事件的方式实现,Application Model不能直接操作View,所以某些情况下不能方便的实现业务逻辑。

接着前面说的调节音量的例子,这次我们加个新功能,不再通过鼠标拖动滚动条来调整音量大小,而是给出一个文本框,让用户直接通过键盘输入阿拉伯数字表示音量大小,一旦用户输入非法内容(比如说英文字符),背景色变黄以示警告。问题是如果用户输入非法内容,就不应该改变Model的状态,但不改变Model的状态,View就没有机会收到渲染的事件。

三、MVP

大概上世纪九十年代,IBM的Mike Potel提出了MVP(Model-View-Presenter)的概念。

  • Model 定义使用者接口所需要被显示的资料模型,一个模型包含着相关的商业逻辑。
  • View 视图为呈现使用者接口的终端,用以表现来自 Model 的资料,和使用者命令路由再经过 Presenter 对事件处理后的资料。
  • Presenter 包含着元件的事件处理,负责检索 Model 取得资料,和将取得的资料经过格式转换与 View 进行沟通。

与此同时,Smalltalk团队正在开发新一代框架,当他们看到MVP时,发现它不仅和MVC非常相似,并且很好的解决了复杂逻辑的问题,所以决定使用它,出于复杂度的关系,他们简化了MVP,最终看上去更像是把原本的MVC扭转了60°,把其中的VC颠倒了一下顺序:

mvp

 

View截获用户请求,然后委派给Presenter,Presenter改变Model的状态,Model通过Observer Synchronization通知View自己的状态发生了变化,View查询Model展现数据。

最重要的是一点是Presenter和View彼此持有对方的引用。虽然View截获用户请求,但它并不处理,而是委派给Presenter处理,保证了可测试性,同时,因为Presenter可以直接操作View,不必受限于观察者模式。

接着前面说的调节音量的例子,当用户通过鼠标拖动滚动条来调整音量大小时,View截获请求,并把请求委派给Presenter,如果Presenter发现音量大于临界值,直接操作View实现逻辑;当用户通过键盘输入音量大小时,View截获请求,并把请求委派给Presenter,如果Presenter发现内容非法,直接操作View实现逻辑。

Martin Fowler分析了MVP的实现方式,分类为

1、 Supervising Controller

Supervising-Controller

 

2、 Passive View

Passive-View

二者的区别在于Model和View是否有联系,在Supervising Controller的实现中,View可以查询Model,Model状态发生变化的话会通知View,而在Passive View的实现中,View不可以查询Model,Model状态发生变化的话会通知Presenter,由Presenter完成View的渲染。比较而言,Passive View的可测试性更好一些,但Presenter的代码量相应大些。

前面我们讨论了MVC到MVP的演化史,随着Web的兴起,人们开始把MVC,MVP等知识应用到Web环境下,但Web环境有其特殊性,最重要的一点就是HTTP是无状态的,每次请求都是独立的,所以不可能实现观察者模式。

四、Web MVC

Java是Web MVC最早的实践者,开发出 Model 2,使用JavaBean,JSP,Servlet分别对应MVC中的三个组成部分,紧接着 Structs的出现开始让大众注意到Web MVC,不过真正让Web MVC流行起来的却是Ruby on Rails,其大致流程如下图所示:

web_mvc

一个典型的Web MVC流程:

  1. Controller截获用户发出的请求
  2. Controller调用Model完成状态的读写操作
  3. Controller把数据传递给View
  4. View渲染最终结果并呈献给用户

在Classic MVC中,Controler可以改变Model的状态,View可以查询Model的状态,所以说对Model而言,Controller和View的地位是平等的,不过在Web MVC中,Controller变成了中继者,主要工作是协调Model和View,如此看来,Web MVC中的Controller等同于MVP中的Presenter。那为什么不叫Web MVP,而称之为Web MVC?这是因为截获请求的是Controller而不是View。

五、MTV

Python的Django框架宣称自己使用的是MTV,其实质仍然是Web MVC。Django将MVC中的视图进一步分解为 Django视图 和 Django模板两个部分,分别决定 “展现哪些数据” 和 “如何展现”,使得Django的模板可以根据需要随时替换,而不仅仅限制于内置的模板。至于MVC控制器部分,由Django框架的URLconf来实现。

Django 里关注的是模型(Model)、模板(Template)和视图(Views),分别为:

  • Model,即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • Template,即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  • View,即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

mtv

需要注意的是,不能简单的把 Django视图认为是MVC控制器,把 Django 模板认为MVC视图。 区别在于:

  • Django 视图 不处理用户输入,而仅仅决定要展现哪些数据给用户;
  • Django 模板 仅仅决定如何展现Django视图指定的数据。

六、Web MVP

在Desktop的时代,微软通过WinForms实现MVP,把组件化编程发挥到了极致,大大提升了开发效率,随着Web的兴起,微软希望延续这样的编程模式,所以使用WebForms实现了Web MVP,引入了CodeBehind,ViewState等设计概念。

web-forms

当一个浏览器向服务器请求一个aspx页面时的简体步骤如下:

  1. 服务器会首先创建前台页面aspx类的对象,当子类(aspx类)被创建时,父类(后台页面CS类)也会顺便被创建。
  2. 接着就会在前台页面类中调用ProcessRequest方法(PR方法不是在前台页面类中定义的,而是在Page类中定义的,
  3. 因为CS类继承与page类,而aspx类又继承与page类,所以PR方法相当于aspx类的爷爷类中定义的)。
  4. 在PR方法中调用BuildControlTree方法,把前台页面所有的html控件和runat=server的控件转成对应的控件对象并添加在前台页面
  5. 类得Controls集合中(这里当前页面即aspx页面类是根节点),而且runat=server的控件对象会保存在后台CS类中的一个对应类型的变量中。
  6. 在PR方法中调用后台页面CS类的Page_Load方法,这个方法中的代码是程序员自己写的。
  7.  最后再PR方法中调用Render_Controls方法,来遍历控件树中每一个节点的Render_Controls方法,生成完整的html代码
  8.  把完整的html代码返回给浏览器。

 七、 ASP.NET MVC

微软同时又推出了类似Web MVC的ASP.NET MVC,但是在截获请求部分还是存在着一些差别,具体请看下图:

asp_net_mvp_vs_mvc

ASP.NET MVC的具体工作流程为:

asp.net_mvc

当用户从浏览器输入地址,发出页面请求,到返回结果,一般经过以下步骤:

  1. 当用户输入地址,发出请求时,实际上就是向控制器发出相关命令
  2. 控制器接收用户指令后,向模型请求获得相关数据
  3. 模型将对应的数据返回给控制器
  4. 控制器将有关数据发送到指定视图
  5. 指定的视图呈现指定的数据

Web Forms构建web相对容易,开发人员只需在一个可视化设计器中拖放控件,设置相关属性即可,通过编写代码来响应事件,使得对于程序的逻辑操作非常直观。但是,开发人员很难了解背后HTML是如何运行的,同时,如果没有合理控制ViewState的话,页面的尺寸将大大超过预期,使得页面打开相当缓慢,随着web应用的复杂化,不容易测试也是开发中面对的一个问题.

MVC避免了Web Forms所带来的复杂性,没有数据回传,没有页面中保存视图状态,开发者可以完全掌握页面呈现的全过程,使用模型、视图及控制器将web划分为不同的组件,有利于开发与设计的分离,也提高了程序的可维护性和扩展性,特别是利于应用程序的测试,可以比较容易的实施测试驱动开发。

两种开发技术并存。 MVC只是给开发者提供了开发web应用程序的一种选择,而不是替代传统的Web Forms,这两种技术应用于不同的场合具有不同的优缺点。具体两者之间的比较分析,可以查看 WebForms vs. MVC

八、MVVM

Model-View-ViewModel是一种架构模式,主要在WPF、Silverlight和WP7开发里使用,它的目标是从视图层移除几乎所有代码隐藏(code-behind)。MVVM是更加通用的 Presentation模式的一个具体实现。MVVM视图模型包含概念模型而不是数据模型,所有业务逻辑和其它操作都是在模型和视图模型里完成的。

IC606760

在WPF/Silverlight中应用MVVM模式,View主要用于界面呈现,ViewModel用于逻辑实现,Model用于数据的构造,而这三者能够进行通信,最重要的是通过WPF/Silverlight中强大的数据绑定机制,将View和ViewModel有效的联系起来。

mvvm

使用MVVM架构最大的好处是:开发人员在写程序的时候不需要做UI,而设计人员可以使用Microsoft Expression Blend 4+设计全部的UI并且不需要写任何代码。主要的好处如下:

  1. 设计人员可以用设计工具很容易的设计UI,而且不需要写任何代码
  2. 你可以更好的设计UI,而且可以让即使不是开发人员使用。
  3. 可以先设计UI或者与开发同时设计。
  4. 当UI全部改变时,代码可以不改变。

为了达到以上要求。当你设计UI时,后台不能有任何代码。并且UI与应用程序通过Bindings和Commands相互交互,其中Bindings和Commands在ViewModel中设计。

Model层主要为应用程序提供数据。其主要包含

  • Web Services:SilverLight应用程序的特点就是必须通过Web service取得数据,你可以调用Web Service中的方法。
  • Rest Services:和Web Services一样
  • Generic Collections:任何类型的数据集合

View Model一般有以下三个部分组成

  • 属性:一个事物,它的类型可以是一个字符型,也可以是一个对象。实现接口INotifyPropertyChanged,那么任何UI元素绑定到这个属性,不管这个属性什么时候改变都能自动和UI层交互。
  • 集合:事物的集合,它的类型一般是ObservableCollection,因此,任何UI元素绑定到它,不管这个集合什么时候改变,都可以自动的与UI交互。
  • Commands:一个可以被触发的事件,并且可以传递一个类型为Object的参数。但是前提是要实现接口ICommand。

这一层可以用Expression Blend设计,不用写任何代码。主要有以下三个部分组成

  1. 把View Model层的属性绑定到 text box, radio button, toggle button, MediaElement, trigger an animation or ViewState change
  2. 把View Model层的集合绑定到ListBox,TreeView,DataGrid
  3. Commands

使用InvokeCommandAction实现以下behavior

  • A、绑定View Model层的ICommand
  • B、指出你需要实现的ICommand(比如Click事件,Selected事件。。。)
  • C、传递参数

参考文章:

http://aviadezra.blogspot.com/2008/06/mvc-model-view-controller-design.html

http://aviadezra.blogspot.com/2007/07/twisting-mvp-triad-say-hello-to-mvpc.html

http://huoding.com/2011/05/02/64

http://www.cnblogs.com/888h/archive/2010/12/24/1915214.html

相关 [mvc] 推荐:

MVC演化史

- huige - 火丁笔记
Martin Fowler在他所写的《企业应用架构模式》一书中感慨道:MVC已经成为我们最常误用的模式. 人们之所以常常误用MVC,很大程度上是因为混淆了不同的MVC变体. 大概上世纪七十年代,Xerox PARC的Trygve提出了MVC的概念,并应用在Smalltalk系统中,为了和其它类型的MVC加以区分,历史上习惯的称之为Classic MVC.

Spring MVC 和 Struts2

- - CSDN博客架构设计推荐文章
Web层面的框架学习了三个Struts1和2,SpringMVC,那他们之间肯定存在一个优劣和适用的环境,Struts1和2的异同点我已经做过对比《 Struts1和Struts2》,这篇将对比下Struts2和SpringMVC的异同,下面数据基本来源于网络,本人是搜集整理所得,供大家参考. 一个项目使用什么样的技术,决定的因素很多,我所能想到的有:对系统的性能、开发的效率、团队学习的成本、业务场景等,下面尽量从这几个方面入手,来分析比较下他们之间存在的优劣.

最佳MVC实践

- - CSDN博客架构设计推荐文章
原文地址 http://www.yiiframework.com/doc/guide/1.1/zh_cn/basics.best-practices 最佳MVC实践(Best MVC Practices). Although Model-View-Controller (MVC) is known by nearly every Web developer, how to properly use MVC in real application development still eludes many people.

srping mvc RequestMapping实现

- - CSDN博客推荐文章
spring mvc中定义请求的url只需要在方法上添加注解: @RequestMapping("aa.mvc")即可定义访问的url地址,但是你是否有考虑过为什么添加这个注解就可以实现url访问地址的定义了呢. 首先定义注解RequestMapping. mvc中常需要对输入值进行合法性校验,所以也定义了校验的注解MyValid.

MVC就是个选择题

- Dash - Becomin' Charles
由于采用了Web开发框架来开发项目,所以我首次在真正的项目中采用MVC的开发模式. 随着项目的不断深入,我也在不断反思,MVC设计模式到底给项目带来了什么. 听起来都很难听对吗,但是确实如此. 清晰的代码结构,易于维护,易于扩展. 当然,我不是在批判MVC,只是觉得,在使用MVC过程中,还是需要投入更深入的思考,到底怎样才能用好这个设计模式.

表现层模式-MVC

- - 博客园_首页
       在前面简述了从服务层到数据层参见 架构设计目录. 剩下了表现层,一个再好的中间层表现也必须有一个用户界面,提供和用户交互,将用户行为输入转化为系统操作,进入后台逻辑. 在当下RAD(快速应用开发)工具的支持下,我们可以比较快速的完成UI设计,RAD追求所见即所得的快速反馈,快速应用.

三层架构与MVC

- - CSDN博客推荐文章
MVC是Model View Controller , 是模型-视图-控制器的缩写,一种软件设计典范.用于组织代码用 一种业务逻辑和数据显示分离的方法,这个方法的假设挑剔是如果业务逻辑被聚集到一个部件里面,而且界面和用户围绕数据的交互能被改进和个性化指定而不需要重新编写业务逻辑.. 三层架构是最基本的项目分层结果,而MVC则是三层架构的一个变体,MVC是一种好的开发模式.

Spring MVC 3 深入总结

- - 企业架构 - ITeye博客
大家好,Spring3 MVC是非常优秀的MVC框架,由其是在3.0版本发布后,现在有越来越多的团队选择了Spring3 MVC了. Spring3 MVC结构简单,应了那句话简单就是美,而且他强大不失灵活,性能也很优秀. 官方的下载网址是: http://www.springsource.org/download   (本文使用是的Spring 3.0.5版本).

Spring MVC 与 web开发

- - 码蜂笔记
项目组用了 Spring MVC 进行开发,觉得对里面的使用方式不是很满意,就想,如果是我来搭建开发环境,我会怎么做. 下面就是我的想法,只关注于 MVC 的 View 层. 现在基本上都是用 ajax 来调用后台接口,拿到 json格式的数据再展示,有的人直接返回数据,却没有考虑异常的情况,我觉得返回的报文里必须包含表示可能的异常信息的数据和业务响应数据.

Spring MVC的常见错误

- - Java译站
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准. 然而多年过后,我发现Spring MVC已经越来越流行了. 对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性. 从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误.