当目光超越 RAD (拖放和配置)构建用户界面的方式,许多工具鼓励您可能会遇到三种设计模式,称为 模型-视图-控制器, 模型-视图-呈现器模型-视图-视图模型. 。我的问题分为三个部分:

  1. 这些模式解决了哪些问题?
  2. 它们有何相似之处?
  3. 它们有何不同?
有帮助吗?

解决方案

模型-视图-呈现器

MVP, ,Presenter 包含 View 的 UI 业务逻辑。所有从 View 委托直接到 Presenter 的调用。Presenter 也直接与 View 解耦,并通过接口与其进行对话。这是为了允许在单元测试中模拟视图。MVP 的一个共同特点是必须有大量的双向调度。例如,当有人单击“Save”按钮时,事件处理程序将委托给 Presenter 的“OnSave”方法。一旦保存完成,Presenter就会通过其接口回调View,以便View显示保存已完成。

MVP 往往是在 Web 表单中实现分离表示的非常自然的模式。原因是视图始终首先由 ASP.NET 运行时创建。你可以 了解有关这两种变体的更多信息.

两个主要变化

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

  • 专业人士:最大可测试表面;视图和模型完全分离
  • 缺点:更多工作(例如所有 setter 属性),因为您自己进行所有数据绑定。

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

  • 专业人士:通过利用数据绑定,可以减少代码量。
  • 缺点:可测试的表面较少(由于数据绑定),并且视图中的封装较少,因为它直接与模型对话。

模型-视图-控制器

在里面 多维控制器, ,控制器负责确定显示哪个视图以响应任何操作(包括应用程序加载时)。这与 MVP 不同,MVP 中的操作通过视图路由到演示者。在 MVC 中,视图中的每个操作都与对控制器的调用以及操作相关。在网络中,每个操作都涉及对 URL 的调用,在 URL 的另一端有一个控制器进行响应。一旦该控制器完成其处理,它将返回正确的视图。该序列在应用程序的整个生命周期中以这种方式继续:

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

MVC 的另一大区别是视图不直接绑定到模型。视图只是渲染,并且是完全无状态的。在 MVC 的实现中,视图的代码后面通常不会有任何逻辑。这与 MVP 相反,MVP 是绝对必要的,因为如果 View 不委托给 Presenter,它就永远不会被调用。

演示模型

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

有一个 有关表示模型的 MSDN 文章 以及其中的一个部分 WPF 复合应用程序指南 (前棱镜)关于 分离的呈现模式

其他提示

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

多维控制器

MVC

MVP

enter image description here

我不久前在博客上谈到了这一点,引用了 托德·斯奈德 (Todd Snyder) 关于两者之间差异的精彩帖子:

以下是模式之间的关键差异:

MVP模式

  • 视图与模型的耦合更加松散。主持人负责将模型与视图结合。
  • 更易于单位测试,因为与视图的相互作用是通过接口
  • 通常查看与演示者的映射是一一对应的。复杂的观点可能具有多演示者。

MVC模式

  • 控制器基于行为,可以通过视图共享
  • 可以负责确定要显示哪个视图

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

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

enter image description here

enter image description here

MVP 是 不是 必然是视图负责的场景(例如,参见 Taligent 的 MVP)。
我发现不幸的是,人们仍然将其视为一种模式(负责视图)而不是反模式,因为它与“这只是一种视图”(务实程序员)相矛盾。“这只是一个视图”表明向用户显示的最终视图是应用程序的次要关注点。Microsoft 的 MVP 模式使视图的重用变得更加困难并且 方便地 为微软的设计师鼓励不良做法开脱。

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

考虑 非常令人兴奋的文章,全面列出了许多这些不同的实现。您可能会注意到,它们基本上都在做相同的事情,但略有不同。

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

最有价值球员:视图是负责的。

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

中层控制器:控制器负责。

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

enter image description here

MVC(模型视图控制器)

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

MVP(模型视图演示者)

输入从视图开始,而不是演示者。View 和关联的 Presenter 之间存在一对一的映射。视图持有对演示者的引用。Presenter 也会对 View 触发的事件做出反应,因此它知道与其关联的 View。Presenter 根据它在 Model 上执行的请求操作来更新 View,但 View 不支持 Model。

了解更多 参考

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

用户:单击单击...

看法: :那是谁?[MVP|多维控制器]

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

看法: :好的,请稍等……。[MVP|多维控制器]

( 看法 呼叫 主持人|控制器 … ) [MVP|多维控制器]

看法: :嘿 主持人|控制器, ,用户刚刚点击了搜索按钮,我该怎么办?[MVP|多维控制器]

主持人|控制器: :嘿 看法, ,该页面上有任何搜索词吗?[MVP|多维控制器]

看法: :是的,……这里是……“钢琴”[MVP|多维控制器]

主持人: :谢谢 看法,...同时我正在查找搜索词 模型, ,请向他/她显示进度条[MVP|多维控制器]

( 主持人|控制器 正在呼叫 模型 … ) [MVP|多维控制器]

主持人|控制器: :嘿 模型, 您是否有与此搜索词匹配的内容?:“钢琴”[MVP|多维控制器]

模型: :嘿 主持人|控制器, ,我查一下……【MVP|多维控制器]

( 模型 正在查询电影数据库...) [MVP|多维控制器]

( 一段时间后 ...)

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

模型: :我给你找到了一份清单 主持人, ,这里是 JSON 格式“[{"name":"Piano Teacher","year":2001},{"name":"Piano","year":1993}]”[MVP]

模型: :有一些结果可用, 控制器. 。我在实例中创建了一个字段变量并用结果填充它。它的名称是“searchResultsList”[多维控制器]

(主持人|控制器 谢谢 模型 并回到 看法) [MVP|多维控制器]

主持人: :感谢您的等待 看法, ,我为您找到了匹配结果列表,并将它们以可观的格式排列:[《钢琴老师2001》、《钢琴1993》]。请以垂直列表的形式向用户展示。另外请立即隐藏进度条[MVP]

控制器: :感谢您的等待 看法, , 我问过了 模型 关于您的搜索查询。它表示它已找到匹配结果列表并将其存储在其实例内名为“searchResultsList”的变量中。你可以从那里得到它。另外请立即隐藏进度条[多维控制器]

看法: :非常感谢 主持人 [MVP]

看法: :谢谢“管制员”【多维控制器] (现在 看法 正在质疑自己:我应该如何呈现我从 模型 给用户?电影的制作年份应该排在第一位还是最后一位......?它应该在垂直列表中还是水平列表中?...)

如果您感兴趣,我一直在撰写一系列有关应用程序架构模式(MVC、MVP、MVVP、干净架构……)的文章,并附有 Github 存储库 这里. 。尽管该示例是为 Android 编写的,但基本原理可以应用于任何媒体。

  • MVP = 模型-视图-演示者
  • MVC = 模型-视图-控制器

    1. 两种呈现模式。它们分离了模型(认为域对象)、屏幕/网页(视图)以及 UI 的行为方式(呈现器/控制器)之间的依赖关系
    2. 它们在概念上非常相似,人们根据喜好以不同的方式初始化演示者/控制器。
    3. 关于差异的一篇很棒的文章是 这里. 。最值得注意的是 MVC 模式让模型更新视图。

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

使用被动视图时,您的视图通常会实现一个细粒度的接口,其中的属性或多或少直接映射到底层 UI 小部件。例如,您可能有一个具有名称和地址等属性的 ICustomerView。

您的实现可能如下所示:

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

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

MVP 的第二种类型是监督控制者。在这种情况下,您的视图可能有一个名为 Customer 的属性,该属性再次与 UI 小部件进行数据绑定。您不必考虑同步和微观管理视图,监督控制器可以在需要时介入并提供帮助,例如使用完整的交互逻辑。

MVP 的第三个“风格”(或者有人可能会称其为单独的模式)是表示模型(或有时称为模型-视图-视图模型)。与 MVP 相比,您将 M 和 P“合并”为一个类别。您拥有 UI 小部件数据绑定到的客户对象,但您还拥有其他特定于 UI 的字段,例如“IsButtonEnabled”或“IsReadOnly”等。

我认为我发现的 UI 架构的最佳资源是 Jeremy Miller 在以下网站上发表的一系列博客文章 构建您自己的 CAB 系列目录. 。他涵盖了 MVP 的所有风格,并展示了实现它们的 C# 代码。

我还在 Silverlight 的上下文中撰写了关于模型-视图-视图模型模式的博客,网址为 重新访问 YouCard:实现 ViewModel 模式.

模型-视图-控制器

多维控制器 是软件应用程序架构的模式。它将应用程序逻辑分为三个独立的部分,从而促进模块化以及易于协作和重用。它还使应用程序更加灵活并欢迎迭代。它将应用程序分为以下组件:

  • 楷模 用于处理数据和业务逻辑
  • 控制器 用于处理用户界面和应用程序
  • 意见 用于处理图形用户界面对象和演示

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

enter image description here

模型-视图-呈现器

  • 模型 是将在视图(用户界面)中显示的数据。
  • 看法 是一个显示数据(模型)并将用户命令(事件)路由到 Presenter 以根据该数据执行操作的界面。视图通常有对其 Presenter 的引用。
  • 主持人 是“中间人”(由 MVC 中的控制器扮演),并且引用视图和模型。 请注意“模型”一词 具有误导性。更应该是 检索或操作模型的业务逻辑. 。例如:如果您有一个在数据库表中存储用户的数据库,并且您的视图想要显示用户列表,则演示器将引用您的数据库业务逻辑(如 DAO),演示器将在其中查询用户列表。

如果您想查看简单实现的示例,请检查 github 帖子

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

是什么 不同之处 之间 多维控制器MVP 模式?

MVC模式

  • 控制器基于行为并且可以在视图之间共享

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

MVP模式

  • 视图与模型的耦合更加松散。演示者负责将模型绑定到视图。

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

  • 通常查看与演示者的映射是一一对应的。复杂的视图可能有多个演示者。

它们各自解决不同的问题,甚至可以组合在一起形成如下所示的内容

The Combined Pattern

还有 MVC、MVP 和 MVVM 的完整比较在这里

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

有讨论 这里 关于 MVC 与 MVP 之间的差异。

区别在于,在 MVC 应用程序中,传统上视图和控制器与模型交互,但彼此之间不交互。

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

话虽如此,根据这些定义,ASP.NET MVC 是一个 MVP 框架,因为控制器访问模型来填充视图,而视图没有逻辑(仅显示控制器提供的变量)。

要了解 ASP.NET MVC 与 MVP 的区别,请查看 这个 MIX 演示 作者:斯科特·汉塞尔曼。

两者都是试图分离表示和业务逻辑,将业务逻辑与 UI 方面解耦的模式

从架构上来说,MVP 是基于页面控制器的方法,而 MVC 是基于前端控制器的方法。这意味着在 MVP 中,标准 Web 表单页面生命周期只是通过从后面的代码中提取业务逻辑来增强。换句话说,页面是为 http 请求提供服务的页面。换句话说,MVP 恕我直言是 Web 形式的进化类型的增强。另一方面,MVC完全更改了游戏感觉,MVC外观(至少在我看来)可以通过路由引擎增强MVP的控制器风味

它们都支持 TDD,并且各有利弊。

恕我直言,如何选择其中之一的决定应该取决于人们在 ASP NET Web 表单类型的 Web 开发上投入了多少时间。如果一个人认为自己擅长 Web 表单,我会建议 MVP。如果人们对页面生命周期等事情感觉不太舒服,MVC 可能是一种选择。

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

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

我使用过 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

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

在 MVP 中,您可以让一个视图与多种类型的演示者一起工作,也可以让一个演示者与不同的多个视图一起工作。

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

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

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

然后,您可以将许多不同类型的演示者绑定到视图,所有演示者都必须具有 Maker 属性 - 它可以是飞机、火车或其他任何东西,视图并不关心。视图从呈现器中提取数据——无论是哪一个——只要它实现了约定的接口。

这个绑定框架,如果你把它拆下来,它实际上是控制器:-)

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

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

结论 - MVP 和 MVC 都是 UI 模式的解耦,但 MVP 通常使用底层的 MVC 绑定框架。因此,MVP 处于比 MVC 更高的架构级别,是 MVC 之上的包装模式。

我粗浅的看法:MVP 适用于大规模,MVC 适用于小规模。对于 MVC,我有时觉得 V 和 C 可能被视为单个不可分割组件的两侧,而不是直接绑定到 M,当缩小到较小的规模(例如 UI 控件和基本小部件)时,不可避免地会陷入这种情况。在这种粒度级别上,MVP 没有什么意义。相反,当规模更大时,正确的接口就变得更加重要,明确的职责分配也是如此,这就是 MVP。

另一方面,当平台特性有利于组件之间的某种关系时,例如在 Web 中,实现 MVC 似乎比 MVP 更容易,这种经验法则的权重可能很小。

来自 Uncle Bob 的精彩视频,他在最后简要解释了 MVC 和 MVP。

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

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

希望这能有更好的帮助。

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

这次演讲 droidcon NYC 2017 - 使用架构组件进行简洁的应用程序设计 澄清它

enter image description here enter image description here

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

我认为这张图片由 Erwin Vandervalk 拍摄(以及随附的 文章)是对 MVC、MVP 和 MVVM 以及它们的异同的最好解释。这 文章 不会出现在有关“MVC、MVP 和 MVVM”查询的搜索引擎结果中,因为文章标题不包含“MVC”和“MVP”一词;但我认为这是最好的解释。

image explaining MVC, MVP and MVVM - by Erwin Vandervalk

(这 文章 也符合鲍勃·马丁叔叔在他的一次演讲中所说的:MVC 最初是为小型 UI 组件设计的,而不是为系统架构设计的)

MVP

MVP 代表模型 - 视图 - 演示者。这在 2007 年初就出现了,当时 Microsoft 推出了智能客户端 Windows 应用程序。

Presenter在MVP中充当监督角色,绑定模型中的视图事件和业务逻辑。

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

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

优点:视图只有UI没有任何逻辑高的可检验性

缺点:实现事件绑定时有点复杂且需要更多工作

多维控制器

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

控制器是发起者,它决定渲染哪个视图。

优点:强调单个职责原理高水平的可检验性

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top