什么是MVP和MVC,有什么区别?
当超越RAD (拖放和configuration)构build用户界面的方式(许多工具鼓励您)时,您很可能会遇到三种名为Model-View-Controller , Model-View-Presenter和Model-View-ViewModel的devise模式。 我的问题有三个部分:
- 这些模式解决什么问题?
- 他们怎么样?
- 他们有什么不同?
模型 – 视图 – 演示
在MVP中 ,Presenter包含View的UI业务逻辑。 所有来自View的调用都直接发送给Presenter。 Presenter也直接从View中解耦,并通过一个接口与它交谈。 这是为了允许在unit testing中嘲笑视图。 MVP的一个共同特点是必须有很多双向调度。 例如,当有人点击“保存”button时,事件处理程序将委托给演示者的“OnSave”方法。 保存完成后,演示者将通过其界面callback视图,以便视图可以显示保存已完成。
MVP往往是一个非常自然的模式,在Web窗体中实现分离的演示文稿。 原因是View始终是由ASP.NET运行时首先创build的。 你可以find更多关于这两个变种 。
两个主要的变化
被动视图:视图尽可能愚蠢,并包含几乎为零的逻辑。 演讲者是一个与视图和模型交谈的中间人。 视图和模型完全被屏蔽。 该模型可能引发事件,但演示者订阅它们以更新视图。 在被动视图中,没有直接的数据绑定,而是视图暴露了演示者用来设置数据的setter属性。 所有状态都在演示者而不是视图中进行pipe理。
- Pro:最大可测性表面; 清晰地分离视图和模型
- Con:更多的工作(比如所有的setter属性),因为你正在自己完成所有的数据绑定。
监督控制器:演示者处理用户手势。 视图通过数据绑定直接绑定到模型。 在这种情况下,演示者的工作就是将模型传递给视图,以便它可以绑定到视图。 演示者还将包含按下button,导航等手势的逻辑。
- 临:通过利用数据绑定的代码量减less。
- Con:由于数据绑定,可testing表面较less,View中的封装较less,因为它直接与Model对话。
模型 – 视图 – 控制器
在MVC中 ,控制器负责确定显示哪个视图以响应包括应用程序何时加载的任何操作。 这与动作通过视图路由到演示者的MVP不同。 在MVC中,视图中的每个动作都与调用Controller和一个动作相关联。 在networking中,每个动作都涉及一个URL的调用,而另一个则有一个控制器响应。 一旦该控制器完成处理,它将返回正确的视图。 整个申请的整个过程都以这种方式继续:
在视图中的行动 - >调用控制器 - >控制器逻辑 - >控制器返回视图。
关于MVC另外一个很大的区别就是View并不直接绑定到Model上。 视图简单地呈现,并且是完全无状态的。 在MVC的实现中,视图通常在代码后面没有任何逻辑。 这与MVP完全相反,因为如果View没有委托给Presenter,它将永远不会被调用。
演示模型
另一种模式是演示模式。 在这个模式中,没有演示者。 相反,视图直接绑定到演示模型。 演示模型是专门为视图制作的模型。 这意味着这个模型可以暴露一个永远不会放在域模型上的属性,因为这会违反分离关注点。 在这种情况下,表示模型绑定到域模型,并可以订阅来自该模型的事件。 该视图然后订阅来自演示模型的事件并相应地自我更新。 Presentation Model可以暴露视图用于调用操作的命令。 这种方法的优点是,当PM完全封装视图的所有行为时,可以基本上删除代码隐藏。 这种模式是在WPF应用程序中使用的非常强大的候选者,也称为Model-View-ViewModel 。
有一个关于演示模型的MSDN文章和WPF复合应用指南 (之前的Prism)关于分离表示模式的章节
我在这个博客上写了一些内容,引用了托德·斯奈德(Todd Snyder)关于两者差异的出色文章 :
以下是模式之间的主要区别:
MVP模式
- 视图更松散地耦合到模型。 主持人负责将模型绑定到视图上。
- 更容易unit testing,因为与视图的交互是通过一个接口
- 通常查看演示者映射一对一。 复杂的观点可能有多个主持人。
MVC模式
- 控制器基于行为,可以在视图中共享
- 可以负责确定要显示哪个视图
这是网上我能find的最好的解释。
这是对这些devise模式的许多变种的过度简化,但这是我想如何考虑两者之间的差异。
MVC
MVP
这里是代表沟通stream程的插图
MVP不一定是View负责的场景(例如参见Taligent的MVP)。
我觉得不幸的是,人们仍然把这个模式(负责看法)说成是一种模式,而不是反模式,因为它与“只是一种观点”(Pragmatic Programmer)相矛盾。 “这只是一种观点”表示,向用户展示的最终视图是应用程序的次要关注点。 微软的MVP模式使视图的重复使用变得更加困难和方便 ,从而鼓励微软devise师不鼓励坏习惯。
坦率地说,我认为MVC的基本问题适用于任何MVP实现,差异几乎完全是语义的。 只要你关注视图(显示数据),控制器(初始化和控制用户交互)和模型(底层数据和/或服务)之间的分离问题,那么你正在享受MVC的好处。 如果你正在享受的好处,那么谁真的关心你的模式是MVC,MVP还是监督控制器? 唯一真正的模式仍然是MVC,其余的只是不同的味道。
考虑这个非常令人兴奋的文章,全面列出了一些这些不同的实现。 你可能会注意到,他们基本上都在做同样的事情,但是略有不同。
我个人认为MVP最近才作为一个引人注目的术语被重新引入,以减less争论是否是真正的MVC的语义偏执狂之间的争论,或者certificate微软快速应用开发工具的合理性。 我的书中的这些理由都不是作为一个单独的devise模式来certificate它的存在。
MVP:观点负责。
在大多数情况下,这种看法创造了主持人。 演示者将与模型交互并通过界面操作视图。 视图有时会与主持人交互,通常通过某个界面。 这归结为执行; 你想让视图调用演示者的方法,还是希望视图有演示者监听的事件? 归结起来:这个观点知道主持人。 观点代表主持人。
MVC:控制器负责。
控制器是根据某个事件/请求创build或访问的。 控制器然后创build适当的视图并与模型交互以进一步configuration视图。 归结为:控制器创build和pipe理视图; 该视图是控制器的从属。 视图不知道控制器。
MVC(模型视图控制器)
input首先指向Controller,而不是视图。 该input可能来自用户与页面的交互,但也可能来自于将特定的urlinput到浏览器中。 在任何一种情况下,它都是一个控制器,用来启动一些function。 控制器和视图之间有多对一的关系。 这是因为单个控制器可能会根据正在执行的操作来select不同的视图。 请注意从控制器到视图的单向箭头。 这是因为View对控制器没有任何了解或引用。 控制器确实传回了模型,所以视图和期望的模型之间有知识传递给它,而不是控制器服务它。
MVP(模型查看演示者)
input始于View,而不是Presenter。 视图和相关的Presenter之间有一对一的映射关系。 该视图保存对演示者的引用。 演示者也对从View触发的事件作出反应,所以它意识到与其关联的View。 演示者根据在模型上执行的请求操作更新视图,但视图不是模型感知的。
欲了解更多参考
- MVP = Model-View-Presenter
-
MVC =模型 – 视图 – 控制器
- 两种演示模式。 他们将模型(思考域对象),屏幕/网页(视图)和你的用户界面如何performance(演示者/控制器)之间的依赖关系分开,
- 它们在概念上相当相似,人们根据口味对演示者/控制器进行不同的初始化。
- 关于差异的一个伟大的文章在这里 。 最值得注意的是,MVC模式有模型更新视图。
还值得记住的是,也有不同types的MVP。 福勒把模式分为两种 – 被动观察和监督控制。
当使用被动视图时,你的视图通常实现一个细粒度的界面,其属性或多或less直接映射到底层的UI小部件。 例如,你可能有一个ICustomerView属性,如名称和地址。
你的实现可能看起来像这样:
public class CustomerView : ICustomerView { public string Name { get { return txtName.Text; } set { txtName.Text = value; } } }
Presenter类将与模型进行交谈并将其“映射”到视图。 这种方法被称为“被动视图”。 好处是视图很容易testing,并且在UI平台(Web,Windows / XAML等)之间移动更容易。 缺点是你不能利用像数据绑定(这在WPF和Silverlight等框架中非常强大)。
MVP的第二个口味是监督控制器。 在这种情况下,您的视图可能会有一个名为Customer的属性,然后再次将数据绑定到UI小部件。 您不必考虑同步和微观pipe理视图,并且监督控制器可以介入并在需要时提供帮助,例如使用压缩的交互逻辑。
MVP的第三个“味道”(或某人可能称之为单独的模式)是Presentation Model(或有时称为Model-View-ViewModel)。 与MVP相比,你将M和P合并成一个类。 你有你的客户对象,你的用户界面控件是数据绑定到,但你也有额外的用户界面特定字段,如“IsButtonEnabled”,或“IsReadOnly”等
我认为我发现的UI架构最好的资源是由Jeremy Miller在“build立自己的CAB系列目录”中完成的一系列博客post。 他涵盖了MVP的所有风格,并展示了C#代码来实现它们。
我还在YouCard重新访问过的Silverlight上下文中介绍了Model-View-ViewModel模式:实现ViewModel模式 。
我几年前写了一篇关于交互式应用程序体系结构模式的文章,其中包括对MVC模式和MVP模式变体的详细讨论。 你可以在这里find这篇文章。
这两个框架的目的都是为了分散关注 – 例如,与数据源(模型)的交互,应用程序逻辑(或将这些数据转化为有用的信息)(控制器/演示者)和显示代码(视图)。 在某些情况下,模型也可以用来将数据源转换为更高层次的抽象。 MVC店面项目就是一个很好的例子。
这里有一个关于MVC和MVP之间的区别的讨论。
所做的区别是在MVC应用程序中传统上有视图和控制器与模型交互,但与其他模型没有交互。
MVPdevise让演示者访问模型并与视图进行交互。
话虽如此,ASP.NET MVC是由这些定义MVP框架,因为控制器访问模型填充视图,这是没有逻辑(只显示由控制器提供的variables)。
为了从MVP中获得ASP.NET MVC的区别,请查看Scott Hanselman的MIX演示 。
两者都是试图分离表示和业务逻辑的模式,将业务逻辑从UI方面解耦
在架构上,MVP是基于页面控制器的方法,其中MVC是基于前端控制器的方法。 这意味着在MVP标准的Web表单页面生命周期只是通过从后面的代码中提取业务逻辑来增强。 换句话说,页面是服务于http请求的页面。 换句话说,MVP恕我直言是networkingforms进化型的增强。 MVC另一方面完全改变了游戏,因为请求被加载页面之前被控制器类拦截,业务逻辑在那里被执行,然后控制器处理刚刚转储到页面(“视图”)的数据的结果在那感觉,MVC看起来(至less对我来说)很多MVP的监督控制器风味增强与路由引擎
它们都能够实现TDD,并且具有不利和不利因素。
决定如何select其中的一个,恕我直言,应该基于多less时间投资于ASP NET Web表单types的Web开发。 如果有人认为自己擅长网页forms,我会build议MVP。 如果在页面生命周期等方面感觉不太舒服,那么MVC就可以成为这里的一种方式。
这里有另外一篇博客文章链接,提供了有关这个主题的更多细节
我曾经使用MVP和MVC,虽然我们作为开发人员往往把重点放在两种模式的技术差异,恕我直言,MVP的点与易于采用比任何其他更多。
如果我在一个团队中工作,那么这个团队已经成为Web表单开发风格的一个良好的背景,那么引入MVP要比MVC容易得多。 我会说在这种情况下MVP是一个快速的胜利。
我的经验告诉我,把一个团队从Web表单转移到MVP,然后从MVP转移到MVC是相对容易的。 从网页forms转移到MVC是比较困难的。
我在这里留下了一个关于MVP和MVC的一系列文章的链接。
http://www.qsoft.be/post/Building-the-MVP-StoreFront-Gutthrie-style.aspx
我没有得到的是为什么数据绑定必须降低可testing性。 我的意思是,一个观点是有效地基于可以被认为是一个或多个数据库视图的,对吗? 不同视图中的行之间可能存在连接。 另外,我们可以谈论面向对象而不是关系型,但实际上并没有改变任何东西 – 我们仍然有一个或多个不同的数据实体。
如果我们将编程视为数据结构+algorithm,那么最好是尽可能使数据结构变得更加明确,然后开发algorithm,尽可能less地依赖一小部分数据,algorithm之间的耦合最小?
我在这里感受到了非常类似于Java的FactoryFactoryFactory思维模式 – 我们希望拥有多个视图,多个模型,多个自由度。 这几乎就是MVC和MVP背后的推动力,而不是什么。 现在让我问一下:你为此付出的代价是多less(而且绝对是代价)呢?
我也没有看到如何有效地pipe理HTTP请求之间的状态的讨论。 我们是不是从function性的人们(以及命令性的意大利细面条所犯的大量错误)中学习到这种状态是邪恶的,应该尽量减less(并且在使用时应该很好理解)?
我看到很多MVC和MVP术语的用法,没有太多证据表明人们对它们持批评态度。 显然,问题是“他们”,我,或者两者兼而有之。
你可以在这个问题上find答案:“ 在Windows窗体中实现MVC ”在实现MVC和MVP时讨论不同的选项很有帮助。
在Android中有mvc的版本是mvp:什么是MVP?
MVP模式允许将表示层从逻辑中分离出来,从而使界面工作的一切与我们在屏幕上的performance分离。 理想情况下,MVP模式将实现相同的逻辑可能有完全不同的和可互换的观点。
首先要澄清的是,MVP不是一个架构模式,它只负责表示层。 在任何情况下,最好将它用于您的架构,而不是完全不使用它。
mvp的一个例子是https://github.com/antoniolg/androidmvp
什么是MVC? MVC体系结构是实现问题分离的最古老的模式之一。 MVC由三层组成,即模型,视图和控制器。
经典MVC存在的时候,屏幕上存在的每个控件/小工具被认为是愚蠢的,每个控件都与自己的控制器配对,以pipe理用户之间的交互。 所以如果存在10个小工具,那么必须存在10个控制器。 在这种情况下,每个小工具都被视为一个视图。 Windows GUI系统的出现改变了这张图片。 控制器与控制器的关系已经过时了。 控制部门获得了对用户发起的行动作出反应的情报。 在Windows世界中,视图是所有控件/小配件都存在的表面,因此只需要一个控制器。 视图可以接收事件并触发控制器帮助进行进一步处理。
这两者之间的区别可在这里http://www.codeproject.com/Articles/288928/Differences-between-MVC-and-MVP-for-Beginners
现在根据我的经验,你必须使用基于android项目的MVP,因为它增强了MVC模型的版本。
我简短的看法:MVP是大规模的,MVC是小规模的。 有了MVC,我有时觉得V和C可能被看作是一个单一的不可分割的组件的两侧,而不是直接绑定到M,而下降到这个时候不可避免地会下降到更小的尺度,比如UI控件和基础小部件。 在这个粒度级别上,MVP没什么意义。 当相反的规模变得更大时,正确的界面变得更加重要,明确的责任分配也是如此,这里就是MVP。
另一方面,当平台特性有利于组件之间的某种关系时,拇指的这种规模规则可能会减轻很多,就像在网页中,MVC似乎更容易实现MVP,而不是MVP。
在MVP中,视图从呈现器绘制数据,该视图从模型中绘制和准备/规范化数据,而在MVC中,控制器从模型中绘制数据并设置,通过在视图中推入。
在MVP中,您可以使用单个视图来处理多种types的演示者和使用不同多个视图的单个演示者。
MVP通常使用某种绑定框架,例如Microsoft WPF绑定框架或HTML5和Java的各种绑定框架。
在这些框架中,UI / HTML5 / XAML知道演示者每个UI元素显示的属性,因此,当您将视图绑定到演示者时,视图将查找属性并知道如何从中绘制数据,以及在用户在UI中更改值时设置它们。
因此,例如,如果模型是一辆汽车,那么主持人就是某种汽车主持人,将汽车属性(年份,制造商,座位等)展现给观众。 该视图知道称为“汽车制造商”的文本字段需要显示演示者Maker属性。
然后,您可以绑定到许多不同types的主持人的视图,都必须具有制造商属性 – 它可以是飞机,火车或任何事情,视图不关心。 该视图从演示者提取数据 – 不pipe是哪一个 – 只要它实现了一个被认可的界面。
这个绑定框架,如果你把它剥下来,它实际上是控制器:-)
所以,你可以把MVP视为MVC的演变。
MVC是伟大的,但问题是,通常它的控制器每个视图。 控制器A知道如何设置视图A的字段。如果现在,你想让视图A显示模型B的数据,你需要控制器A来知道模型B,或者你需要控制器A来接收一个带有接口的对象 – 就像MVP只有没有绑定,或者你需要重写控制器B中的UI设置代码。
结论 – MVP和MVC都是UI模式的解耦,但MVP通常使用MVC下的绑定框架。 THUS MVP的架构级比MVC更高,而MVC的封装模式更高。
他们分别解决不同的问题,甚至可以结合在一起,有如下所示
这里还有MVC,MVP和MVVM的完整比较
MVP
MVP代表模型 – 视图 – 演示者。 在2007年初,微软推出了Smart Client的Windows应用程序。
演示者在MVP中担当监督angular色,从模型中绑定View事件和业务逻辑。
视图事件绑定将在视图界面中的Presenter中实现。
视图是用户input的发起者,然后将事件委派给演示者,演示者处理事件绑定并从模型中获取数据。
优点:查看只有UI没有任何逻辑高水平的可testing性
缺点:实现事件绑定时有点复杂,工作量更多
MVC
MVC代表模型 – 视图 – 控制器。 Controller负责创build模型并使用绑定模型呈现视图。
控制器是发起者,它决定渲染哪个视图。
优点:强调单一责任原则高水平的可测性
缺点:如果尝试在同一控制器中呈现多个视图,有时控制器的工作量太大。
很多人不知道MVC和MVP中Controller和Presenter的区别。
其中一个简单的等式
MVC视图= MVP的视图和演示者
MVP模型= MVC的控制器和模型
更多信息请参阅http://includeblogh.blogspot.com.eg/2016/07/the-difference-and-relationship-between.html