MVC演化 (转至http://www.cnblogs.com/wubaiqing/archive/2011/10/26/2225438.html)
Classic MVC
Classic MVC 大概上世纪七十年代,Xerox PARC的Trygve提出了MVC的概念。
并应用在Smalltalk系统中,为了和其它类型的MVC加以区分,历史上习惯的称之为Classic MVC。
Classic Mvc模式
Model:封装领域数据及逻辑
View:查询领域数据并展现给用户
Conctroller:截获用户请求并改变领域数据
从依赖关系看,Model不依赖View和Controller,而View和Controller依赖Model。
Classic MVC关注两个分离:
从Model中分离View
从View中分离Controller
从Model中分离View,主要基于以下几点考虑:
不同的关注点:Model关注内在的不可视的逻辑,而View关注外在的可视的逻辑。
多种表现形式:同一个Model往往需要多种View表现形式,如文本、图像。
提高可测试性:相对Model而言,View是不容易测试的。
从View中分离Controller就不那么重要了。
开发软件的时代,View和Controller往往是一一对应的关系,所以常常把他们合并成为UI,事实上,当时多数UI框架都没有实现从View中分离Controller。后来随着Web的兴起,这种分离(模板技术)才开始流行起来。
本质上Classic MVC的结构如下图所示,之所以说本质上,是因为View和Controller其实是彼此关联的,但这种关联和稍后提到的MVP完全不同,更像是一种框架的副产品,为了避免引起混淆,这里省略了它们,具体参阅:How to use Model-View-Controller (MVC)

图解:
Controller截获用户通过鼠标或键盘发出的请求,然后改变Model的状态,Model通过Observer Synchronization通知View自己的状态发生了变化
View查询Model展现数据。
Classic MVC并不完美,不适用于复杂的逻辑。
举个例子:
用户通过鼠标拖动滚动条来调整音量大小,如果音量大于某个数值,背景色变红以示提醒。当使用Classic MVC的时候,如何处理背景色变红的逻辑呢?
有两个选择:
Model触发一个特殊事件,View收到后完成相关逻辑的处理。但我们前面说过,从依赖关系上看,Model应该完全无视View的存在。
在View中判断音量临界值,达到后完成相关逻辑的处理。但我们前面说过,View是不容易测试的,应该尽可能减少逻辑处理。
Application Model MVC
大概上世纪八十年代,ParcPlace从Xerox
Parc划分出来,负责Smalltalk的研发工作,为了适应更复杂的逻辑,开发了Classic MVC的改进版,也就是Application
Model MVC,在原有架构基础上引入了Application Model,如下图所示:

图解:
Application Model在Model和View、Controller之间扮演着一个中继者的角色。
接着看前面的例子,既然Model和View都不适合放背景色变红的逻辑,那么我们可以尝试把相关逻辑放在
Application Model中实现,当用户通过鼠标调整音量大小时,Model触发一个普通事件,Application
Model拦截到这个事件,判断音量是否大于临界值,如果是就触发一个特殊事件,View收到后完成相关逻辑的处理。
Application Model MVC虽然看似解决了复杂逻辑的问题,但它仍然存在硬伤:
首先随着以微软视窗为主的图形化操作系统的兴起,操作系统本身提供了一套原生的View接口,用来截获用户通过鼠标或键盘发出的请求。
结果让Controller显得多余了。
其次由于在Application Model
MVC中,View的渲染只能通过事件的方式实现,Application
Model不能直接操作View,所以某些情况下不能方便的实现业务逻辑。接着前面说的调节音量的例子,这次我们加个新功能,不再通过鼠标拖动滚动条来调
整音量大小,而是给出一个文本框,让用户直接通过键盘输入阿拉伯数字表示音量大小,一旦用户输入非法内容(比如说英文字符),背景色变黄以示警告。问题是
如果用户输入非法内容,就不应该改变Model的状态,但不改变Model的状态,View就没有机会收到渲染的事件。
MVP
大概上世纪九十年代,IBM的Mike Potel提出了MVP的
概念。与此同时,Smalltalk团队正在开发新一代框架,当他们看到MVP时,发现它不仅和MVC非常相似,并且很好的解决了复杂逻辑的问题,所以决
定使用它,出于复杂度的关系,他们简化了MVP,最终看上去更像是把原本的MVC扭转了一个角度,把其中的VC颠倒了一下顺序:

图解:
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的实现方式,分类为Supervising Controller和Passive View。

图解:
MVP的两种分类:Supervising Controller和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社区的Rails,其大致流程如下图所示:

图解:
一个典型的Web MVC流程
Controller截获用户发出的请求
Controller调用Model完成状态的读写操作
Controller把数据传递给View
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。
Python社区的Django框架宣称自己使用的是MTV,其实质仍然是Web MVC。
Web MVP
在Desktop的时代,微软通过WinForms实现MVP,把组件化编程发挥到了极致,大大提升了开发效
率,随着Web的兴起,微软希望延续这样的编程模式,所以使用WebForms实现了Web
MVP,引入了CodeBehind,ViewState等设计概念。WebForms的优点和缺点都很突出,篇幅所限,具体的描述大家可以参考下面链
接:
- 为WebForms说几句话,以及一些ASP.NET开发上的经验(1)
- 为WebForms说几句话,以及一些ASP.NET开发上的经验(2)
- 为WebForms说几句话,以及一些ASP.NET开发上的经验(3)
注:微软推出了ASP.NET MVC向Web MVC靠拢,似乎要两手抓两手都要硬。

图解:
微软Web MVP vs Web MVC。注意截获请求的是Controller还是View!
MVC演化 (转至http://www.cnblogs.com/wubaiqing/archive/2011/10/26/2225438.html)的更多相关文章
- shell脚本中的几个括号总结(小括号/大括号/花括号)--from:http://www.cnblogs.com/hanyan225/archive/2011/10/06/2199652.html
在Shell中的小括号,大括号结构和有括号的变量,命令的用法如下: 1.${var}2.$(cmd)3.()和{}4.${var:-string},${var:+string},${var:=stri ...
- linux下使用tar命令 (转至http://www.cnblogs.com/li-hao/archive/2011/10/03/2198480.html)
解压语法:tar [主选项+辅选项] 文件或者目录 使用该命令时,主选项是必须要有的,它告诉tar要做什么事情,辅选项是辅助使用的,可以选用. 主选项: c 创建新的档案文件.如果用户想备份一个目录或 ...
- http://www.cnblogs.com/youring2/archive/2011/03/28/1997694.html
http://www.cnblogs.com/youring2/archive/2011/03/28/1997694.html
- ArcEngine中打开各种数据源(WorkSpace)的连接http://www.cnblogs.com/feilong3540717/archive/2011/08/07/2129906.html
ArcEngine中打开各种数据源(WorkSpace)的连接 ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影 ...
- http://www.cnblogs.com/yyyyy5101/archive/2011/03/11/1981078.html
http://www.cnblogs.com/yyyyy5101/archive/2011/03/11/1981078.html
- http://www.cnblogs.com/gaojing/archive/2011/08/23/2413616.html
http://www.cnblogs.com/gaojing/archive/2011/08/23/2413616.html
- table-cell http://www.cnblogs.com/StormSpirit/archive/2012/10/24/2736453.html
http://www.cnblogs.com/StormSpirit/archive/2012/10/24/2736453.html
- java反射详解 (转至 http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html)
本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解. 下面开始正文. [案例1]通过一个对象 ...
- http://www.cnblogs.com/hoojo/archive/2011/06/08/2075201.html
http://www.cnblogs.com/hoojo/archive/2011/06/08/2075201.html
随机推荐
- Mark 装修建材 清单
装修攻略 介绍 装修公司:东易.龙发.金螳螂.乐豪斯乳胶漆:多乐士,立邦.三棵树.晨阳水漆.华润.都芳瓷砖:马可波罗.东鹏瓷砖.蒙娜丽莎.诺贝尔.简一瓷砖.欧神诺瓷砖.金舵瓷砖.卓远瓷砖.鹰牌.兴辉瓷 ...
- java mac install
http://docs.oracle.com/javase/8/docs/technotes/guides/install/mac_jdk.html#A1096855 This page descri ...
- uva 10537 Toll! Revisited(优先队列优化dijstra及变形)
Toll! Revisited 大致题意:有两种节点,一种是大写字母,一种是小写字母. 首先输入m条边.当经过小写字母时须要付一单位的过路费.当经过大写字母时,要付当前財务的1/20做过路费. 问在起 ...
- 如何把scratch转成一个swf文件或者exe执行文件
scratch作为一款启蒙用的积木式编程软件,非常受人欢迎,但是,现在有一个问题就是,无法将之转变成一个可执行文件,以便和周边的人们分享. 我个人认为把scratch转变为一个可执行的exe文件,并不 ...
- Bash Shell启动配置脚本的顺序
1.Bash检查环境变量文件的方式,取决于系统运行Shell的方式,通常系统运行Shell有3种方式: )通过系统用户登陆后默认运行的Shell )非登陆交互式运行Shell )执行脚本运行非交互式S ...
- php读取sqlite数据库入门实例
php读取sqlite数据库的例子,php编程中操作sqlite入门实例.原文参考:http://www.jbxue.com/article/php/22383.html在使用SQLite前,要确保p ...
- webBench&ad网站并发测试工具
webBench 测试工具使用,网站上线前压力测试工具. ad测试工具
- rabbitmq增加vhost
查看当前rabbitmq上的vhost列表: # rabbitmqctl list_vhosts Listing vhosts ... / vhost2 添加名为demo的vhost虚似主机: rab ...
- C++友元详解
1.什么是友元在一个类A中,将类B声明为友元类,则类B可以访问类A的私有成员和保护成员.另外,也可以将函数声明为友元函数. 2.什么时候用到友元若不同的类之间某些共享数据成员,可以使用友元,简化类的设 ...
- CentOS 7.0 以后的几件事情
1.当最大化时隐藏标题栏 或者使用tweak tool 在字体中将标题栏字体设置为0...建议这个方法. 2.添加epel源 yum -y --nogpgcheck install http://do ...