当超越RAD(拖放和配置)构建用户界面的方式时,许多工具都鼓励您使用三种设计模式,即模型视图控制器、模型视图演示器和模型视图视图模型。我的问题有三个部分:

这些模式解决了什么问题?它们有什么相似之处?它们有何不同?


当前回答

MVC(模型视图控制器)

在MVC中,控制器是负责人!控制器根据一些事件/请求触发或访问,然后管理视图。

MVC中的视图实际上是无状态的,控制器负责选择要显示的视图。

例如:当用户单击“Show MyProfile”(显示我的配置文件)按钮时,将触发控制器。它与模型通信以获得适当的数据。然后,它会显示一个类似于配置文件页面的新视图。控制器可以从模型中获取数据并将其直接馈送到视图(如上图所示),或者让视图从模型本身获取数据。

MVP(模型视图演示者)

在MVP中,视图是负责人!每个视图都会调用其演示者或演示者收听的某些事件。

MVP中的视图不实现任何逻辑,演示者负责实现所有逻辑,并使用某种接口与视图进行通信。

例如:当用户单击“保存”按钮时,视图中的事件处理程序将委派给演示者的“OnSave”方法。演示者将执行所需的逻辑,并与模型进行任何所需的通信,然后通过其界面调用视图,以便视图显示保存已完成。

MVC与MVP

MVC并没有让视图负责,视图充当控制器可以管理和指导的从属对象。在MVC中,视图是无状态的,而MVP中的视图是有状态的,可以随时间变化。在MVP中,视图没有逻辑,我们应该尽可能让它们保持沉默。另一方面,MVC中的视图可能有某种逻辑。在MVP中,演示者与视图分离,并通过接口与视图对话。这允许在单元测试中模拟视图。在MVP中,视图与模型完全隔离。然而,在MVC中,视图可以与模型通信,以使其与最新的最新数据。

其他回答

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

用户:单击…

观点:那是谁?[MVP|MVC]

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

视图:好的,等一下。[MVP|MVC]

(视图调用演示者|控制器…)[MMVP|MVC]

视图:嗨,演示者|控制器,用户刚刚单击了搜索按钮,我该怎么办?[MVP|MVC]

演示者|控制器:嘿,View,那个页面上有搜索词吗?[MVP|MVC]

视图:是的,…这里是…“钢琴”[MMVP|MVC]

演示者|控制器:谢谢查看,……同时我正在查找模型上的搜索项,请向他/她显示进度条[MVP|MVC]

(演示者|控制器正在调用模型…)[MMVP|MVC]

演示者|控制器:嘿,模特儿,你有匹配这个搜索词的吗?:“钢琴”[MVP|MVC]

模型:嘿,演示者|控制器,让我检查一下…〔MVP|MVC〕

(模型正在对电影数据库进行查询…)[MVP|MVC]

(过了一会儿…)

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

模型:我为您找到了一个列表,演示者,这里是JSON格式的“[{“name”:“Piano Teacher”,“year”:2001},{“name:”Piano”,“year”:1993}]”[MVP]

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

(演示者|控制器感谢模型并返回视图)[MMVP|MVC]

演示者:感谢等待View,我为您找到了一个匹配结果列表,并以可呈现的格式排列:[“Piano Teacher 2001”,“Piano 1993”]。请在垂直列表中向用户显示。也请现在隐藏进度条[MMVP]

控制器:感谢等待View,我已经向Model询问了您的搜索查询。它说它找到了一个匹配结果的列表,并将它们存储在其实例中名为“searchResultsList”的变量中。你可以从那里得到它。也请立即隐藏进度条[MVC]

观点:非常感谢演示者MVP

视图:谢谢“控制器”[MVC](现在,视图正在质疑自己:我应该如何向用户展示我从模型中获得的结果?电影的制作年份应该是第一年还是最后一年……?它应该在垂直列表还是水平列表中?…)

如果你感兴趣的话,我一直在写一系列关于应用程序架构模式(MVC、MVP、MVVP、干净架构……)的文章,并在这里附上Github repo。尽管该示例是为android编写的,但其基本原理可以应用于任何介质。

MVC(模型视图控制器)

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

MVP(模型视图演示者)

输入以视图开始,而不是演示者。视图和关联的演示者之间有一对一的映射。视图包含对演示者的引用。演示者也会对从视图触发的事件做出反应,从而了解与其关联的视图。演示者根据对模型执行的请求操作更新视图,但视图不支持模型。

更多参考信息

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

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

这两种方法都支持TDD,并有其优缺点。

关于如何选择其中一个IMHO的决定应该基于在ASP.NET web表单类型的web开发中投入的时间。如果有人认为自己擅长网络形式,我会建议MVP。如果你在页面生命周期等方面感觉不太舒服的话,MVC可能是一种方法。

下面是另一个博客文章链接,提供了关于这个主题的更多细节

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

MVP不一定是视图负责的场景(例如,参见Taligent的MVP)。我觉得很不幸的是,人们仍在宣扬这是一种模式(主管视图),而不是一种反模式,因为它与“这只是一种观点”(实用主义程序员)相矛盾。“这只是一个视图”表示,向用户显示的最终视图是应用程序的次要关注点。微软的MVP模式使视图的重用变得更加困难,并方便地为微软的设计师提供了避免不良做法的借口。

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

考虑一下这篇激动人心的文章,它全面列出了许多不同的实现。你可能会注意到,他们基本上都在做相同的事情,但略有不同。

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

你忘了动作域响应程序(ADR)。

正如上面的一些图形所解释的,MVC中的模型和视图之间有直接的关系/链接。在控制器上执行操作,控制器将在模型上执行操作。模型中的该操作将触发视图中的反应。视图在模型状态更改时始终更新。

有些人一直忘记了,MVC是在70年代末创建的,而Web只是在80年代末/90年代初创建的。MVC最初不是为Web创建的,而是为桌面应用程序创建的,其中Controller、Model和View将共存。

因为我们使用的是仍然使用相同命名约定(模型-视图-控制器)的web框架(例如:.Laravel),所以我们倾向于认为它必须是MVC,但实际上是其他东西。

相反,请查看操作域响应程序。在ADR中,控制器获得一个动作,该动作将在模型/域中执行操作。到目前为止,情况是一样的。不同的是,它然后收集该操作的响应/数据,并将其传递给Responder(例如:.view())进行渲染。当在同一组件上请求新操作时,将再次调用Controller,并重复循环。在ADR中,模型/域和视图(Reposer的响应)之间没有任何联系。

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

mvc adr模型视图控制器动作域响应器