Model View Presenter vs Model View Controller
简介
在我工作中经常需要处理一些由于开发人员没能很清楚地理解MVC和MVP模式的区别的情况下使用它们而产生的问题。在这篇文章中我将会阐述一下我对两者之间区别的一些理解。
在N层体系结构中MVC/P
模式仅仅只是用于表示层(presentation layer),理解这一点很重要。这两个模式并不是关于怎么构建数据层(data
layer)和服务层(service
layer)的,而是关于怎么将数据(data)从用户接口(view)中分离出来,以及用户接口如何与数据进行交互的。这些模式的使用让解除你的程序中表示层对对数据和控制逻辑的依赖,从而可以自由的变更表示层。
这两种模式中三个部分的一般理解
1、模型(Model)表示数据模型和业务逻辑(business
logic)。模型并不总是DataSet,DataTable之类的东西,它代表着一类组件(components)或类(class),这些组件或类
可以向外部提供数据,同时也能从外部获取数据并将这些数据存储在某个地方。简单的理解,可以把模型想象成“外观类(facade
class)”。【译注:这里的外观是指“外观模式”中所说的外观。外观的一般作用是为一个复杂的子系统提供高层次的简单易用的访问接口,可以参看下面的图来理解它的原理:
】
2、视图(View)将数据层现给用户。一般的视图都只是包含用户界面(UI),而不包含界面逻辑。比如,Asp.net中包含控件的页面(page)就是一个视图。视图可以从模型中读取数据,但是不能修改或更新模型。
3、层现器(Presenter)/控制器(Controller)包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知控制器,而控制器负责从视图中取得数据然后发送给模型。
MVC/P模式的核心是为了将模型从视图/控制器中分离出来,从而使得模型独立于它们,因此模型不包含对视图和控制的引用。
什么是MVC(Model View Presenter)模式?
1、为了使得视图接口可以与模型和控制器进行交互,控制器执行一些初始化事件
2、用户通过视图(用户接口)执行一些操作
3、控制器处理用户行为(可以用观察着模式实现)并通知模型进行更新
4、模型引发一些事件,以便将改变发告知视图
5、视图处理模型变更的事件,然后显示新的模型数据
6、用户接口等待用户的进一步操作
这一模式的有一下几个要点:
1、视图并不使用控制器去更新模型。控制器负责处理从视图发送过来的用户操作并通过与模型的交互进行数据的更新
2、
控制器可以和视图融合在一块。Visual Studion中对Windows
Forms的默认处理方式就是这样的。【译注:比如我们双击一个Button,然后在它的事件里写处理逻辑,然后将处理的数据写回模型中。这里处理逻辑时
间应该是控制器的功能,但是我们并没有专门写一个控制器来做这件事情而是接受了VS的默认处理方式,将它写在Form的代码中,而这里的Form在MVC
中它就是一个View。所以这说vs默认的处理方式是将把控制器和视图融合在一起的。】
3、控制器不包含对视图的渲染逻辑(rendering logic)
“主动—MVC”模式,也是通常意义下的MVC模式
【译
注:为什么说是主动的?View不是等Controller通知它Model更新了然后才从Model取数据并更新显示,而是自己监视Model的更新
(如果用观察者模式)或主动询问Model是否更新。前面那种等待Controller通知的方式是下面所介绍的“被动—MVC”的实现方式。】
“被动—MVC”模式
与主动MVC的区别在于:
1、模型对视图和控制器一无所知,它仅仅是被它们使用
2、控制器使用视图,并通知它更新数据显示
3、视图仅仅是在控制器通知它去模型取数据的时候它才这么做(视图并不会订阅或监视模型的更新)
4、控制器负责处理模型数据的变化
5、控制器可以包含对视图的渲染逻辑
MVP模式
与“被动—MVC模式”很接近,区别在于“视图并不使用模型”。在MVP模式中视图和模型是完全分离的,他们通过Presenter进行交互。
Presenter与控制器非常相似,但是它们也有一些的区别:
1、Presenter处理视图发送过来的用户操作(在MVC中视图自己处理了这些操作)
2、它用更新过的数据去更新模型(在被动MVC中控制器只是通知视图去更新过的模型中去取新的数据,而主动MVC中模型通知视图去更新显示,控制器不需要做工作)
3、检查模型的更新(与被动MVC一样)
4、(与MVC的主要区别)从模型中取数据然后将它们发送到视图中
5、(与MVC的主要区别)将所做的更新告知视图
6、(与MVC的区别)用Presenter渲染视图
MVP的优势
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所以的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presener用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
MVP的问题
由于对视图的渲染放在了Presenter中,所以视图和Persenter的交互会过于频繁。
还有一点你需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的
联系过于紧密。一旦视图需要变更,那么
Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。
MVP模式根据 Module,View,Presenter之间的交互,可以分为Passive View(常规MVP)和Supervising Controller 2种。
Passive View模式:
大
家会发现MVP与MVC最大的一个区别就是“Model与View层之间倒底该不该通信(甚至双向通信)。我想这也是目前做这两方面研究的专家所互相争论
的战场。必定各有各的好处和因好处要付出的代价。起码在MVP模式下的Presenter要拥有“绝对权力”。如果没有它,MODEL与View就是两个
孤岛,尽管各有各的地盘(完全解耦),但不会给企业带来什么有用的价值。
所以我这里有一个比喻来形容MVP中的:
Presenter ----就是一个控制欲极强的女人,甚至就连“用什么姿势”,它都要管一管。
当
然日里万机操心多了就会让自己要做的事越来越多,最终它面临的就是该层代码日益庞杂,且书写起来不太方便,必定就连事件绑定这类鸡毛算皮的事都要归它管,
累不累呀。最终我们看到MVP中的View就真的代码轻闲了不少(国企职工嘛),难怪说View只要从相应的[IVIEW]接口下实现相应的属性和一些简
单方法就完事了,而最终调用[IVIEW]接口下的那个视图实例则完全交给了Presenter,这让我想到了MVC中可以支持“自定义模版引擎(最终由
MVC框架来控制使用系统还是自定义的模版引擎)”以及平时大家常挂在嘴边的换肤功能,想到这里多少还真有那么点意思了(精神层面上)。
当然在微软内部对MVP的理解也有所不同,如下面中所说的Supervising Controller模式和之前大家看到的PassiveView.
Supervising Controller模式其实很接近于MVC的那张图了,只是又提供了Presenter与View之间的“双向通信”。这种做法也是有很多不同意见的,起码对那些支持“单向依赖”的开发者而言是“嗤之以鼻”的。
说到这里,虽然PassiveView模式有些霸道,但必定是让Model和View之间真正解耦,为开发者提供了最大的“控制成就感”,可以说想怎么控制视图就怎么控制,但因此所造成的问题就是代码书写量和实现复杂性等问题了。