从MVC说起 - 概念(Version 1.0)

来源:互联网 发布:linux 运行sh脚本 编辑:程序博客网 时间:2024/06/03 10:19

MVC模式可能是被人们谈起最多的模式,但同时也可能是被误解最多的模式。MVC产生的背景是什么?MVC分别表示什么?它与MVP之间的关系是什么?类似的问题还有许多,在本文中,我们从MVC的起源开始探索一下它的前生今世,以试图回答这些问题。而在随后的文章中,我将从代码的角度回答这些问题。

MVC模式属于GUI模式,因此它的出现是为了解决GUI程序设计中的一些普通存在的问题,这些问题包括:

1. 谁负责与用户交互?

2. 谁负责处理视图逻辑?

3. 谁负责更新模型?

4. 模型发生改变后,谁负责更新视图?

5. M, V, C的作用范围?

概括起来就是说M, V, C的职责是什么?不同的模式对这些问题的回答具有很大的差异,这也正是令人混淆的原因所在。

1 经典MVC

大约在1978-1979年,Trygve Reenskaug第一次正式提出了MVC模式,它的前身是Thing-Model-View-Editor。后来此模式的一个变种作为Xerox PARC Smalltalk-80类库的一部分被实现,关于此实现的描述可以在Application Programming in Smalltalk-80(TM): How to use Model-View-Controller(MVC)中找到。经典MVC的结构如图1所示,其中右侧的结构图来自Aviad's Blog中一篇文章"Twisting the MVC Triad - MVP Design Pattern",形象生动的说明了MVC模式中各个组件的功能及作用范围。

图1 经典MVC模式

在经典MVC中,Controller负责拦截用户动作(即输入),视图负责显示数据(即输出),ControllerView可以直接修改Model,并且通过Model交互。View(和Controller)都观察Model,这样多个widget可以同步更新而不必相互通信。至于ControllerView之间的关联更多的是为了定位的目的。

需要注意的一个问题就是,每种模式的提出都是为了解决当时所面临的一些问题,就像评价历史人物一样我们需要站在人物所处的时代去研究他,MVC第一次提出是在70年代,它的主要目的是分离表示(Presentation)和领域模型(Domain Model),这也是它的核心所在,其后出现的各种变种也都是为了更好的分离表示和模式。只是由于后来的GUI环境已经发生了太多的变化,例如控件的出现使得控件本身就可以拦截用户动作,而在经典MVC中这是Controller的职责。M, V, C的作用范围也是一个很重要的区别。在经典MVCApplication Model MVC中,用户界面上的每一个Widget(小物件,类似于控件)都包含一个View和一个Controller,用户对Widget的动作由它包含的Controller拦截处理,但是随着控件的出现,控件本身已经可以拦截用户动作,因此最终导致了Controller的消失。

注意:本段使用的是拦截(intercept)而不是处理,意思是用户动作的处理可能会转交给其它对象,就像我们在MVP模式中看到的那样。

2 Application Model MVC模式

2同样来自Avaid的博客,展示了Application Model MVC模式中各个组件的关系,职能。

 

2 Application Model MVC模式

1980年前后,从Xerox Parc实验室分离span off出的ParcPlace ,负责Smalltalk的市场和开发,ParcPlace Smalltalk也称为Visual Works,在这个框架中引入了一个新的实体Application Model,它作为ModelView之间的协调者,负责视图逻辑(View Logic)。ViewController不在依赖Model,转而依赖Application Model

Application Model MVC 的一个亮点在于Application Model的引入,它与MVP模式中的Presenter有点类似,都负责视图逻辑,只是Application Model还不够彻底,不能直接访问View,而只能触发某些特殊的事件,让View监听这些事件并更新自己,这种处理视图的方式显得非常笨拙。除此以外,其它方面与经典MVC基本相似。

3 Talgent MVP

1996年,Mike Potel在他的论文,MVP: Model-View-Presenter The Ta nt Programming Model for C++ and Java,正式提出了MVP模式,结构如下图所示。

图3 Taligent MVP模式

Model指应用程序中的数据和业务功能。Selections指出操作的是Model中的哪些数据。Commands定义了数据可以执行的操作。View作为Model的可视化表示,它由应用程序界面中的Widgets组成。Interactors指出如何将用户事件映射到针对Model的操作,例如鼠标移动,键盘输入等。Presenter负责创建ModelSelectionsCommandsViewsInteractors,并且控制应用程序的执行。

在这个模型中,Interactor类似于经典MVCController,它负责拦截用户动作,但是如何处理用户动作是由Presenter决定的,它会对Model应用合适的Commands/SelectionsPresenter的功能被大大的加强了,它的角色就好像是一个子系统的管理者。

另外,在Ta nt MVP中,抛弃了每个Widget都有一个View的做法,而是多个Widgets对应一个View,而且PresenterView一般是一一对应的,或者一个Presenter管理多个Views

4 Dophin Smalltalk MVP

图4 Dophine Smalltalk MVP

上图摘自论文Twisting The Triad The evolution of the Dolphin Smalltalk MVP application framework,从图中可以看出,Dophin Smalltalk MVP通过去掉了SelectionsCommandsInteractors从而简化了Ta nt MVPDophin Smalltalk MVPTa nt MVP的主要区别体现在以下几个方面:

1. PresenterView的关系更加紧密,Presenter可以直接修改View

2. View中的Widget已经可以拦截大部分用户动作并处理其中的一部分。

3. 某些情况下,View可以直接更新Model,但是大多数情况下用户事件委托给Presenter处理。

MVP设计模式分离了视图和它的表现逻辑,允许它们独立的改变。View可以看作是widgets的联合体,它不包含任何描述widget如何响应用户交互的行为,widgets对应于Forms/Controls模型中的控件,并且viewcontroller联系在一起。

Widgets拦截用户动作,然后转交给Presenter处理,Presenter决定如何响应。当Potel讨论这种交互时主要使用术语actions on model,这是通过命令系统和selections系统完成的。

MVC模式的演化可以看出,随着技术的发展,各个组件的职责发生了很大的变化。Controller完全消失了,这是因为随着ViewWidget的功能越来越丰富,它承担了拦截用户动作和部分处理任务。View最初只是简单的呈现模型,现在它已经囊括了Controller的职能,并且有时候可以直接操作Model(当然不提倡这样做,因为这涉及到可测试性的问题)。Presenter从无到有,承担着更新模型和视图的任务,虽然应用数据绑定技术和观察者模式可以很好的同步ModelView,但是由于图形用户界面越来越丰富,交互性越来越强,这就需要更好的协调PresenterView来创造更好的用户体验,我们可以从PresenterView的关系越来越紧密窥见一斑。

5 Suptervising ControllerPassive View

在2006年,Martin FowlerMVP模式分为两个模式,分别命名为Supervising ControllerPassive View。这种区分主要是围绕着Presenter/Controller组件承担表现层逻辑的深度进行的。

注意:这里的Controller与经典MVC中的Controller概念不同,在经典MVC中,Controller主要负责处理用户动作,而Suptervising ControllerPassive View中的Controller实际上相当于MVP模式中的Presenter。作用范围也不一样,在经典MVC中,用户界面中的每一个控件都有自己的ControllerViewController只负责处理它所在的控件的用户动作,而Suptervising ControllerPassive View中,ControllerView都是屏幕级别的。

5.1 Suptervising Controller模式

下面这幅图描述了Suptervising Controller模式的结构

图5 Suptervising Controller模式

Suptervising Controller负责响应来自View的用户输入和处理复杂的表现逻辑,View负责Model呈现和一些简单的表现逻辑。简单表现逻辑特指那些利用数据绑定技术或Observer模式就可以轻松解决的问题。

5.2 Passive View

Passive View模式的结构图如下所示:

图6 Passive View模式

Passive View模式与Supervising Controller模式最大的区别在于ViewModel没有关联,完全依赖Controller执行所有的表现层逻辑。这种结构的可测试性最强,但是需要编写较多的表现层逻辑代码。

至于选择Passive View模式还是Supervising Controller模式,很大程度上取决于个人的喜好,与Passive View模式相比,Supervising Controller模式比较灵活,对于简单的表现逻辑使用数据绑定技术,通过声明式的编程方式,View可以随着Model的改变而改变,

总的来说,MVC模型的演化过程就是职责重新分配的过程,决定这个过程的关键因素是软件技术的发展(控件,数据绑定,模式等),和软件工程思想的发展(可测试性,可维护性等)以及用户体验。

参考文献:

1. GUI Architeture, Martin Flower

2. Twisting The Triad The evolution of the Dolphin Smalltalk MVP Application Framework, Andy Bower, Blair McGlashan

3. MVP: Model-View-Presenter The Ta nt Programming Model for C++ and Java, Mike Potel

4. Twisting the MVC Triad - MVP Design Pattern

5. Interactive Application Architecture Patterns

6. MVC WiKi

后记:

在阅读了多篇关于MVCMVP模式论文之后,试着总结了其中的一些要点,并添加了自己的一些理解之后写成本文。其中关于MVC或者P的职责解释不一定全面透彻,不过基本意思应该是正确的。考虑到MVP模式在GUI编程中的重要性,建议使用一种MVC框架,使用前需要了解框架的结构。

中文有各种各样的输入法可以帮助我们快速输入中文,不知道英文有没有英文输入法?

Powered by Zoundry


http://blog.csdn.net/dreamliner/article/details/2643538