什么是MVP和MVC,有什么区别?

时间:2008-08-05 10:06:33

标签: design-patterns model-view-controller user-interface mvp glossary

当超越RAD(拖放和配置)构建用户界面的方式时,许多工具鼓励您可能会遇到三种名为Model-View-ControllerModel-View-PresenterModel-View-ViewModel的设计模式{{3}}。我的问题有三个部分:

  1. 这些模式解决了哪些问题?
  2. 它们有什么相似之处?
  3. 他们有什么不同?

24 个答案:

答案 0 :(得分:1909)

模型 - 视图 - 演示

MVP 中,Presenter包含View的UI业务逻辑。 View中的所有调用都直接委托给Presenter。 Presenter也直接与View分离,并通过界面与之对话。这是为了允许在单元测试中模拟View。 MVP的一个常见属性是必须进行大量的双向调度。例如,当有人单击“保存”按钮时,事件处理程序将委托给Presenter的“OnSave”方法。保存完成后,Presenter将通过其界面回调View,以便View可以显示保存已完成。

MVP往往是在Web窗体中实现单独呈现的非常自然的模式。原因是View总是首先由ASP.NET运行时创建。你可以find out more about both variants

两个主要变体

被动视图:视图尽可能愚蠢,几乎没有逻辑。演示者是一个与视图和模型对话的中间人。视图和模型完全相互屏蔽。模型可能会引发事件,但Presenter会订阅它们以更新视图。在Passive View中没有直接数据绑定,而View公开了Presenter用于设置数据的setter属性。所有状态都在Presenter中管理,而不是视图。

  • Pro:最大可测性表面;清晰分离视图和模型
  • Con:更多工作(例如所有setter属性),因为您自己正在进行所有数据绑定。

监督控制器: Presenter处理用户手势。 View直接通过数据绑定绑定到Model。在这种情况下,Presenter的工作是将Model传递给View,以便它可以绑定到它。演示者还将包含手势逻辑,如按下按钮,导航等。

  • Pro:通过利用数据绑定,减少了代码量。
  • Con:可测试的表面较少(因为数据绑定),并且View中的封装较少,因为它直接与模型对话。

模型 - 视图 - 控制器

MVC 中,Controller负责确定要响应任何操作(包括应用程序加载时)显示的视图。这与MVP不同,其中操作通过View路由到Presenter。在MVC中,View中的每个操作都与对Controller的调用以及操作相关联。在网络中,每个动作都涉及对URL的调用,在URL的另一侧有一个Controller响应。控制器完成处理后,将返回正确的视图。在整个应用程序的生命周期中,序列以这种方式继续:

    Action in the View
        -> Call to Controller
        -> Controller Logic
        -> Controller returns the View.

MVC的另一个重要区别是View不直接绑定到Model。视图简单地呈现,并且完全是无状态的。在MVC的实现中,View通常不会在后面的代码中有任何逻辑。这与MVP完全相反,因为如果View没有委托给Presenter,它将永远不会被调用。

演示模型

要看的另一个模式是 Presentation Model 模式。在这种模式中没有Presenter。相反,View直接绑定到Presentation Model。 Presentation Model是专为View设计的模型。这意味着此模型可以公开一个永远不会放在域模型上的属性,因为它会违反关注点分离。在这种情况下,表示模型绑定到域模型,并可以订阅来自该模型的事件。 View然后订阅来自Presentation Model的事件并相应地更新自身。表示模型可以公开视图用于调用操作的命令。这种方法的优点在于,您可以完全删除代码隐藏,因为PM完全封装了视图的所有行为。此模式非常适合在WPF应用程序中使用,也称为Model-View-ViewModel

MSDN article about the Presentation Model(前棱镜)中有一个Composite Application Guidance for WPF和一个关于Separated Presentation Patterns的部分

答案 1 :(得分:413)

这是对这些设计模式的许多变体的过度简化,但这就是我想要考虑两者之间差异的方式。

<强> MVC

MVC

<强> MVP

enter image description here

答案 2 :(得分:404)

我暂时在博客上发帖,引用Todd Snyder's excellent post on the difference between the two

  

以下是两者之间的主要区别   模式:

     

MVP模式

     
      
  • 视图与模型的联系更加松散。主持人是   负责将模型绑定到   观点。
  •   
  • 更容易进行单元测试,因为与视图的交互是通过的   界面
  •   
  • 通常一对一地查看演示者地图。复杂的观点可能有   多位主持人。
  •   
     

MVC模式

     
      
  • 控制器基于行为,可以跨越共享   视图
  •   
  • 可以负责确定要显示的视图
  •   

这是我能找到的网上最好的解释。

答案 3 :(得分:237)

以下是代表沟通流程的插图

enter image description here

enter image description here

答案 4 :(得分:160)

MVP 必然是View负责的场景(例如参见Taligent的MVP)。
我发现不幸的是,人们仍在宣传这种模式(负责观点),而不是反模式,因为它与“它只是一种观点”(实用程序员)相矛盾。 “这仅仅是一种观点”指出向用户显示的最终视图是应用程序的次要问题。微软的MVP模式使得重复使用Views变得更加困难,并且方便使微软的设计者免于鼓励不良行为。

坦率地说,我认为MVC的底层问题适用于任何MVP实现,差异几乎完全是语义的。只要您关注视图(显示数据),控制器(初始化和控制用户交互)和模型(基础数据和/或服务)之间的关注点分离,那么您就可以实现MVC的优势。如果您正在获得好处,那么谁真正关心您的模式是MVC,MVP还是监督控制器?唯一的真实的模式仍然是MVC,其余的只是它的不同风格。

考虑this非常激动人心的文章,该文章全面列出了许多不同的实现。 你可能会注意到,他们基本上都做了同样的事情,但略有不同。

我个人认为MVP最近才被重新引入作为一个吸引人的术语,要么减少语义偏执者之间的争论,他们争论某些东西是否真的是MVC,或者证明微软快速应用程序开发工具的合理性。在我的书中,这些原因都不能证明它作为一种单独的设计模式存在。

答案 5 :(得分:103)

MVP:视图负责。

在大多数情况下,视图会创建其演示者。演示者将与模型交互并通过界面操纵视图。视图有时会通过某种界面与演示者进行交互。这归结为实施;您希望视图在演示者上调用方法,还是希望视图具有演示者侦听的事件?它归结为:视图了解演示者。视图委托给演示者。

MVC:控制器负责。

根据某些事件/请求创建或访问控制器。然后,控制器创建适当的视图并与模型交互以进一步配置视图。它归结为:控制器创建和管理视图;视图是控制器的从属。该视图不了解控制器。

答案 6 :(得分:71)

enter image description here

MVC(模型视图控制器)

输入首先指向Controller,而不是视图。该输入可能来自与页面交互的用户,但也可能只是将特定URL输入到浏览器中。在任何一种情况下,它都是一个与之连接的控制器,以启动某些功能。 Controller和View之间存在多对一关系。这是因为单个控制器可以基于正在执行的操作选择要呈现的不同视图。 请注意从Controller到View的单向箭头。这是因为View对控制器没有任何了解或参考。 Controller确实传回了模型,因此View和传递给它的预期模型之间存在知识,但不是控制器为它提供服务。

MVP(模型视图演示者)

输入以View开头,而不是Presenter。 View与关联的Presenter之间存在一对一映射。 View包含对Presenter的引用。 Presenter也对从View触发的事件做出反应,因此它知道与之关联的View。 Presenter根据它在模型上执行的请求操作更新View,但View不支持模型。

了解更多Reference

答案 7 :(得分:42)

这个问题有很多答案,但我觉得需要一些非常简单的答案,清楚地比较两者。这是我在用户在MVP和MVC应用中搜索电影名称时所做的讨论:

用户:点击...

查看:那是谁? [<强> MVP |的 MVC

用户:我刚刚点击了搜索按钮......

查看:好的,等一下...... [<强> MVP |的 MVC

查看调用演示者 | 控制器 ...)[ MVP | MVC

查看:嗨演示者 | 控制器,用户刚刚点击了搜索按钮,我该怎么办? [<强> MVP |的 MVC

演示者 | 控制器:嗨查看,该页面上是否有搜索字词? [<强> MVP |的 MVC

查看:是的,......这里是......“钢琴”[ MVP | MVC ]

演示者:感谢查看,...同时我正在查找模型上的搜索字词,请向他/她显示进度吧[ MVP | MVC ]

Presenter | Controller 正在调用模型 ...)[ MVP | MVC

演示者 | 控制器:嗨模型,您对此搜索字词有匹配吗?:“piano”[ MVP |的 MVC

模型:嗨演示者 | 控制器,让我查一下...... [ MVP | MVC < /强>

模型正在查询电影数据库......)[ MVP | MVC ]

(过了一会......)

--------------这就是MVP和MVC开始分歧的地方---------------

模型:我找到了一个列表, Presenter ,这里是JSON“[{&#34; name&#34;:&#34; Piano老师&#34;,&#34;年&#34;:2001},{&#34;名称&#34;:&#34;钢琴&#34;,&#34;年&#34;:1993}]“[的 MVP

模型:有一些结果可用, Controller 。我在我的实例中创建了一个字段变量,并用结果填充它。它的名字是&#34; searchResultsList&#34; [<强> MVC

演示者 | 控制器感谢模型并返回视图)[ MVP < /强> |的 MVC

演示者:感谢您等待查看,我找到了一份匹配结果列表并以可呈现的格式排列:[&#34;钢琴教师2001&# 34;,&#34;钢琴1993&#34;]。请在垂直列表中向用户显示。同时请隐藏进度条[ MVP ]

控制器:感谢您等待查看,我已经向模型询问了您的搜索查询。它说它找到了一个匹配结果列表,并将它们存储在一个名为&#34; searchResultsList&#34;的变量中。在它的实例中。你可以从那里得到它。同时请隐藏进度条[ MVC ]

查看:非常感谢演示者 [ MVP ]

查看:谢谢你&#34; Controller&#34; [<强> MVC ] (现在 View 正在质疑:我应该如何将 Model 的结果呈现给用户?电影的制作年份应该是第一个还是最后一个...... 。?它应该是垂直还是水平列表?...)

如果您有兴趣,我一直在撰写一系列文章,涉及应用程序架构模式(MVC,MVP,MVVP,干净架构......)以及Github回购here。尽管该示例是为Android编写的,但基本原则可以应用于任何媒介。

答案 8 :(得分:34)

  • MVP = Model-View-Presenter
  • MVC =模型 - 视图 - 控制器

    1. 两种演示模式。它们将模型(思考域对象),屏幕/网页(视图)以及UI的行为方式(演示者/控制器)之间的依赖关系分开。
    2. 它们在概念上非常相似,人们根据品味不同地初始化Presenter / Controller。
    3. 关于差异的一篇很棒的文章是here。最值得注意的是,MVC模式具有模型更新视图。

答案 9 :(得分:32)

另外值得记住的是,MVP也有不同类型。福勒已经将模式分解为两个 - 被动视图和监督控制器。

使用Passive View时,View通常会实现细粒度的界面,其属性或多或少地直接映射到底层UI小部件。例如,您可能有一个ICustomerView,其中包含名称和地址等属性。

您的实施可能如下所示:

public class CustomerView : ICustomerView
{
    public string Name
    { 
        get { return txtName.Text; }
        set { txtName.Text = value; }
    }
}

您的Presenter类将与模型对话并将其“映射”到视图中。这种方法称为“被动视图”。好处是视图易于测试,并且在UI平台(Web,Windows / XAML等)之间移动更容易。缺点是您无法利用数据绑定之类的东西(在WPFSilverlight等框架中真的非常强大。)

MVP的第二种风格是监督控制器。在这种情况下,您的View可能有一个名为Customer的属性,然后再将其数据绑定到UI小部件。您不必考虑同步和微观管理视图,监督控制器可以在需要时介入并提供帮助,例如使用编译的交互逻辑。

MVP的第三个“风味”(或者有人可能称之为单独的模式)是Presentation Model(或者有时称为Model-View-ViewModel)。与MVP相比,您将M和P“合并”为一个类。您拥有UI小部件所绑定的客户对象,但您还有其他UI特定字段,如“IsButtonEnabled”或“IsReadOnly”等。

我认为我在UI架构中找到的最佳资源是Jeremy Miller在The Build Your Own CAB Series Table of Contents完成的一系列博客文章。他涵盖了MVP的所有风格,并展示了C#代码来实现它们。

我还在 YouCard Re-visited: Implementing the ViewModel pattern 的Silverlight上下文中讨论了Model-View-ViewModel模式。

答案 10 :(得分:23)

<强>模型 - 视图 - 控制器

MVC 是软件应用程序架构的模式。它将应用程序逻辑分为三个独立的部分,促进了模块化,易于协作和重用。它还使应用程序更灵活,更热衷于迭代。它将应用程序分为以下组件:

    用于处理数据和业务逻辑的
  • 模型
  • 用于处理用户界面和应用程序的
  • 控制器
  • 用于处理图形用户界面对象和演示文稿的
  • 视图

为了让这一点更清晰,让我们设想一个简单的购物清单应用程序。我们想要的只是我们本周需要购买的每件商品的名称,数量和价格清单。下面我们将描述如何使用MVC实现某些功能。

enter image description here

<强>模型 - 视图 - 演示

  • 模型是将在视图(用户界面)中显示的数据。
  • 视图是一个显示数据(模型)并将用户命令(事件)路由到Presenter以对该数据进行操作的界面。该视图通常引用其Presenter。
  • Presenter 是“中间人”(由MVC中的控制器播放),并且包含对视图和模型的引用。 请注意,“模型”一词具有误导性。它应该是检索或操作模型的业务逻辑。例如:如果您有一个数据库在数据库表中存储User并且您的View想要显示用户列表,那么Presenter将引用您的数据库业务逻辑(如DAO),Presenter将从该列表中查询列表用户。
  

如果您想查看简单实施的样本,请检查   this github post

从数据库查询和显示用户列表的具体工作流程可能如下所示: enter image description here

  

MVC MVP 模式之间的差异是什么?

MVC模式

  • 控制器基于行为,可以跨视图共享

  • 可以负责确定要显示的视图(前端控制器模式)

MVP模式

  • 视图与模型的耦合程度更高。演示者负责将模型绑定到视图。

  • 更容易进行单元测试,因为与视图的交互是通过界面进行的

  • 通常一对一地查看演示者地图。复杂的观点可能有多个演示者。

答案 11 :(得分:19)

他们每个人都解决不同的问题,甚至可以将它们组合在一起以获得类似下面的内容

The Combined Pattern

还有a complete comparison of MVC, MVP and MVVM here

答案 12 :(得分:18)

这两个框架旨在分离关注点 - 例如,与数据源(模型)的交互,应用程序逻辑(或将此数据转换为有用信息)(控制器/演示者)和显示代码(视图)。在某些情况下,模型也可用于将数据源转换为更高级别的抽象。一个很好的例子就是MVC Storefront project

有关MVC与MVP之间差异的讨论here

区别在于MVC应用程序传统上具有视图,控制器与模型交互,但彼此不相互作用。

MVP设计让Presenter访问模型并与视图进行交互。

话虽如此,ASP.NET MVC通过这些定义是一个MVP框架,因为Controller访问Model来填充View,这意味着没有逻辑(只显示Controller提供的变量)。

要想了解ASP.NET MVC与MVP的区别,请查看Scott Hanselman撰写的this MIX presentation

答案 13 :(得分:13)

两种模式都试图将表示和业务逻辑分开,将业务逻辑与UI方面分离

在架构上,MVP是基于页面控制器的方法,其中MVC是基于前端控制器的方法。 这意味着在MVP标准Web表单中,页面生命周期只是通过从后面的代码中提取业务逻辑来增强。换句话说,页面是服务http请求的页面。换句话说,MVP恕我直言是网络形式的进化类型的增强。 MVC另一方面完全改变了游戏,因为在加载页面之前,控制器类拦截了请求,在那里执行了业务逻辑,然后在控制器处理刚刚转储到页面的数据的最终结果(“视图”) 从这个意义上说,MVC看起来(至少对我来说)很多用路由引擎增强的MVP的监督控制器味道

它们都支持TDD并且具有缺点和优势。

关于如何选择其中一个的决定恕我直言应该基于投入ASP NET网络表单类型的Web开发的时间。 如果一个人认为自己在网络形式上很好,我会建议MVP。 如果在页面生命周期等事情上感觉不太舒服,MVC可能是一种可以去的地方。

这是另一篇博客文章链接,提供了有关此主题的更多详细信息

http://blog.vuscode.com/malovicn/archive/2007/12/18/model-view-presenter-mvp-vs-model-view-controller-mvc.aspx

答案 14 :(得分:9)

我已经使用了MVP和MVC,虽然我们作为开发人员倾向于关注两种模式的技术差异,但恕我直言中MVP的要点与其他任何内容的易用性相关。

如果我在一个已经作为Web表单开发风格的良好背景的团队中工作,那么引入MVP要比MVC容易得多。我会说在这种情况下MVP是一个快速的胜利。

我的经验告诉我,将团队从Web表单转移到MVP然后从MVP转移到MVC相对容易;从Web表单转移到MVC更加困难。

我在这里留下了我朋友发表的关于MVP和MVC的一系列文章的链接。

http://www.qsoft.be/post/Building-the-MVP-StoreFront-Gutthrie-style.aspx

答案 15 :(得分:7)

在MVP中,视图从演示者绘制数据,该演示者从模型中绘制和准备/规范化数据,而在MVC中,控制器通过视图中的推送从模型中绘制数据并进行设置。

在MVP中,您可以使用单个视图处理多种类型的演示者,并使用单个演示者处理不同的多个视图。

MVP通常使用某种绑定框架,例如Microsoft WPF绑定框架或HTML5和Java的各种绑定框架。

在这些框架中,UI / HTML5 / XAML知道每个UI元素显示的演示者的属性,因此当您将视图绑定到演示者时,视图会查找属性并知道如何从它们以及当用户在UI中更改值时如何设置它们。

因此,例如,如果模型是汽车,则演示者是某种汽车演示者,将汽车属性(年份,制造商,座位等)暴露给视图。该视图知道名为“car maker”的文本字段需要显示演示者Maker属性。

然后你可以绑定到视图许多不同类型的演示者,所有人都必须具有Maker属性 - 它可以是飞机,火车或者什么,视图不关心。视图从演示者中提取数据 - 无论哪个 - 只要它实现了商定的接口。

这个绑定框架,如果你将其剥离,它实际上是控制器:-)

因此,您可以将MVP视为MVC的演变。

MVC很棒,但问题在于它通常是每个视图的控制器。控制器A知道如何设置视图A的字段。如果现在,您希望视图A显示模型B的数据,您需要控制器A知道模型B,或者您需要控制器A来接收带有接口的对象 - 这就像MVP只有没有绑定,或者您需要重写Controller B中的UI集代码。

结论 - MVP和MVC都是UI模式的解耦,但MVP通常使用一个绑定框架,它是下面的MVC。这个MVP处于比MVC更高的架构级别和MVC之上的包装模式。

答案 16 :(得分:6)

我的简短观点:MVP适用于大型音阶,而MVC适用于小音阶。对于MVC,我有时会觉得V和C可能被看作是单个不可分割组件的两个而不是直接绑定到M,并且当向下到较短的比例时,一个不可避免地会出现这种情况,比如UI控件和基本小部件。在这种粒度级别上,MVP毫无意义。相反,当一个人进入更大的尺度时,适当的界面变得更加重要,同样明确的责任分配,这就是MVP。

另一方面,当平台特性有利于组件之间的某种关系时,拇指的这种缩放规则可能很重,就像在web上一样,它似乎更容易实现MVC,而不是MVP

答案 17 :(得分:2)

来自鲍勃叔叔的this精彩视频,他简要介绍了MVC&amp; amp; MVP最后。

IMO,MVP是MVC的改进版本,您基本上将您将要展示的内容(数据)与您将要展示的内容(视图)区分开来。 Presenter包含了UI的业务逻辑,隐含地强加了应该呈现的数据,并为您提供了一个哑视图模型列表。当需要显示数据时,您只需将视图(可能包含相同的ID)插入适配器,并使用这些视图模型设置相关的视图字段,并引入最少量的代码(仅使用setter方法)。它的主要好处是您可以针对许多/不同的视图测试UI业务逻辑,例如在水平列表或垂直列表中显示项目。

在MVC中,我们通过接口(边界)来讨论粘合不同的层。控制器是我们架构的一个插件,但它没有限制强加什么显示。从这个意义上说,MVP是一种MVC,其概念可以通过适配器插入控制器。

希望这会有所帮助。

答案 18 :(得分:1)

有许多版本的MVC,这个答案是关于Smalltalk中的原始MVC。简而言之,它是 image of mvc vs mvp

这次演讲droidcon NYC 2017 - Clean app design with Architecture Components澄清了它

enter image description here enter image description here

答案 19 :(得分:1)

  • 在MVC中,View具有UI部分,控制器是View与模型和模型之间的中介,模型和模型包含业务逻辑。
  • 在MVP中,View既包含演示者的UI,又包含演示者的实现,因为在此,演示者只是一个接口,模型是相同的,即包含业务逻辑。

答案 20 :(得分:1)

您忘记了 Action-Domain-Responder ADR)。

如上图所示,在MVC中,模型视图之间存在直接关系/链接。 在 Controller 上执行操作,该操作将在 Model 上执行操作。 模型模型)中的该操作将在视图中触发反应。 当模型的状态更改时,视图始终会更新。

有些人忘记了MVC was created in the late 70",而Web仅在80英寸/ 90年代早期创建。 MVC最初不是为Web创建的,而是为桌面应用程序创建的,而Controller,Model和View将并存在一起。

由于我们使用的Web框架(例如:Laravel )仍使用相同的命名约定( model-view-controller ),因此我们倾向于认为它必须是MVC,但实际上是另外一回事。

相反,请看Action-Domain-Responder。 在ADR中,控制器获得一个动作,该动作将在模型/域中执行操作。到目前为止,都一样。 不同之处在于,它随后收集了该操作的响应/数据,并将其传递给 Responder 例如:。view() )进行渲染。 当在同一组件上请求执行新操作时,再次调用 Controller ,然后循环重复进行。 在ADR中,模型/域与视图之间没有没有连接 Reponser的响应)。

注意:维基百科指出,“ 每个ADR操作均由单独的类或闭包表示。”。 不一定是必须的。多个动作可以在同一Controller中,并且模式仍然相同。

答案 21 :(得分:1)

最简单的答案是视图如何与模型交互。在MVP中,视图绑定到演示者,演示者充当视图和模型之间的中介,从视图获取输入,从模型获取数据,然后执行业务逻辑并最终更新视图。在MVC中,模型直接更新视图,而不是通过控制器返回。

答案 22 :(得分:0)

我认为Erwin Vandervalk(及其随附的article)所提供的图像是对MVC,MVP和MVVM及其相似之处和差异的最好解释。 article不会显示在“ MVC,MVP和MVVM”上的查询的搜索引擎结果中,因为文章标题不包含单词“ MVC”和“ MVP”;但我认为这是最好的解释。

image explaining MVC, MVP and MVVM - by Erwin Vandervalk

article也与鲍勃·马丁叔叔在他的一次演讲中所说的相符:MVC最初是为小型UI组件而不是为系统体系结构而设计的)

答案 23 :(得分:-1)

<强> MVP

MVP代表Model - View-Presenter。 2007年初,微软推出了Smart Client Windows应用程序。

Presenter在MVP中扮演监督角色,从模型中绑定View事件和业务逻辑。

视图事件绑定将在视图界面中在Presenter中实现。

View是用户输入的发起者,然后将事件委托给Presenter,演示者处理事件绑定并从模型中获取数据。

<强>优点:     View只有UI而不是任何逻辑     高可测性

<强>缺点:     实现事件绑定时比特复杂,工作更多

<强> MVC

MVC代表模型 - 视图 - 控制器。 Controller负责使用绑定模型创建模型和渲染视图。

Controller是发起者,它决定要渲染的视图。

<强>优点:   强调单一责任原则   高可测性

<强>缺点:   如果尝试在同一个控制器中渲染多个视图,有时控制器的工作负载太多。