MVP与MVVM - 为什么要选择?

16

我在使用WinForm时使用MVP架构,但当我开始使用WPF或Silverlight时,我转向了MVVM架构。

我注意到的唯一变化是,在MVVM模式下,由于强大的绑定功能,我们不需要手动同步视图和ViewModel之间的数据。

我的问题是:

1)使用MVVM的唯一优势是绑定(帮助我们不需要手动同步视图和ViewModel吗)?

2)MVVM比MVP还有其他优势吗?两者的区别是什么?

3)以下代码是MVVP模式、MVVM模式还是两者都是?

interface IView {

  void ShowMessage(string message);

}

class View : IView {
    public void ShowMessage(string message){
              MessageBox.Show(this, message);
    }
}

class ViewModel{

private IView view;

public ViewModel(IVew view){

  this.view = view;

}

........

view.ShowMessage("This is a msg");

}

2
相关的SO帖子:[https://dev59.com/OXRA5IYBdhLWcg3wwwzD] - Marc
这是虚拟机不应该知道视图接口的角色吗? - Mark
如果我想在保存后将焦点设置到控件上怎么办?我是不是应该创建一个附加属性来设置焦点? - Mark
“1)”不是一个问题。 - Slipp D. Thompson
4个回答

17

我知道你的问题是两年前提出的,但是在使用MVVM一年后,我想发表我的看法。

-1- 我不确定你在问什么,但我认为你在问:绑定是MVVM的唯一优势吗?答案是否定的。关注点分离、绑定和高效测试是MVVM的主要优势。还有许多次要的好处,但我不会深入探讨。绑定绝对是非常棒的,因为所有同步都是自动化的,这意味着你需要做的工作更少。此外,关注点分离意味着视图模型不依赖于视图类型,因此您可以使用相同的视图模型来创建多个视图。例如,您创建了一个名为ErrorDataViewModel的视图模型。这个类的目的是保存将显示给用户的ErrorType类列表。ErrorType基本上显示错误信息。ErrorDataViewModel还有一个名为AllErrorsFixed的布尔属性,用于告诉用户列表中的所有错误是否已经修复。AllErrorsFixed是一个简单的属性,它使用linq查询ErrorTypes.Fixed属性的列表。如果全部都被修复,AllErrorsFixed将返回true。

在Application1中,您的客户希望以简单的网格形式显示错误。您所要做的就是将网格绑定到该视图模型的错误列表上。在Application2中,您的客户希望以更具导航性的格式显示错误,以便他们可以逐个表单查看每个错误。那么您所要做的就是将表单控件绑定到列表中的每个错误,并设置导航以从一个记录移动到另一个记录。但是,如果我们希望App1同时利用网格和逐个表单导航,我们也可以做到。更好的是,现在您想使用Silverlight实现Web界面来替换Application1/Application2或作为另一种产品提供,您不必更改视图模型。工作完成了。
我提到了ErrorsFixed布尔值,但是我们忘记在应用程序中实现它了。我所要做的就是进入我的视图,添加一个控件、列或属性测试器,并将其绑定到布尔属性,然后您就完成了。
关于测试,测试可以更有效率,因为您可以编写测试代码来验证视图模型中的更改,而不浪费时间运行应用程序并打开视图。这并不能解决所有测试问题,但它消除了许多耗时的步骤。

-2- MVVM 或 MVP 有任何优势吗?有。一个回答错误地表示在 MVVM 中,一个视图可以有多个 VM,而实际上,一个 VM 可以拥有多个视图,因为它并不绑定到一个视图。或者换句话说,多个视图可以利用一个 VM。因此,在您调用 view.ShowMessage() 的示例中,这不会发生在 MVVM 中,因为您无法保证视图(WPF 或 Silverlight 或测试类)具有 ShowMessage 方法。相反,您要触发一个事件。实际上,Prism 在这方面非常棒,因为它有事件聚合器,所以当您触发一个事件时,事件聚合器处理将该事件发送到分配给事件的视图。因此,每个应用程序的视图都可以根据其自己的需求处理事件。而在 MVP 中,您必须为每个视图创建一个 Presenter,这非常耗时。

-3- 您的示例代码是 MVP。


1
他可能是指一个视图及其子视图可以有不同的视图模型。从技术上讲,您可以根据用户输入或后端事件交换视图模型。 - Millie Smith

8
它们在Android环境中的主要特点。

MVP模式:

  • 由Model、View和Presenter层组成;
  • View将用户输入委托给Presenter;两个层应该有1对1的关系;

  • View和Model没有紧密耦合,以清晰分离关注点;

  • View通过数据绑定直接连接到Model;

  • 易于单元测试,作为Presenter层的接口,可以快速模拟;

MVVM模式:

包括三个关键部分:

  • Model(业务规则、数据访问、类),

  • View(用户界面),

  • ViewModel(作为View和Model之间的代理);
  • 处理与Windows Presentation Foundation系统(WPF)和Silverlight应用程序框架相关的任务的好方法;
  • 提供更清晰的UI和应用程序逻辑分离;
  • 单元测试更容易,因为不依赖于View

功能比较

让我们将MVP与MVVM的要点放在一起进行比较。我们还应该强调,我们不倡导其中一个或一种模式。

代码度量:MVP可能会产生更多的类和Java代码。在MVVM中,有更多的Java类,但每个类的代码更少。

可维护性:MVP易于学习、修改和添加功能。使用MVVM添加新功能可能需要一些对库的经验。

逻辑:在MVP中,View实际上是您的应用程序,而Presenter处理应用程序流程。在MVVM中,代码类(ViewModel)是应用程序,而View是允许用户与应用程序交互的接口。

数据输入:在MVP中,输入始于View,而不是Presenter。在MVVM中,输入始于View,而不是ViewModel。

映射和引用:MVP中View和Presenter之间具有一对一映射,没有引用。在MVVM中,View和ViewModel之间具有一对多映射,没有引用。

最后的话

很明显,架构模式在不断演进。MVVM有成为一个非常好的、令人信服的工具的趋势。与此同时,MVP模式已经足够灵活,受益于各种库。

同样清楚的是,您不必严格遵循MVP或MVVM。在大多数情况下,我们不能纯粹地使用单一模式构建应用程序,这是可以接受的。最重要的是分离视图、模型和它们之间的逻辑。

您可能会问何时使用MVP,何时使用MVVM?建议更多地隐藏在数据绑定中。在无法与数据上下文进行绑定的情况下,大多数开发人员更喜欢MVP(Windows Forms是一个很好的例子)。如果绑定数据上下文,则MVVM是首选,因为界面和代码较少,维护起来更容易。

根据博客提供的资料。


7

举个例子,MVP模式可以清晰地定义为:

view.showMessage("This is a msg");

虽然MVP和MVVM产生的代码在一些简单的例子中看起来很相似,但这两种模式有着显著的不同。如果你认为MVVM只是Microsoft对MVP的另一个称呼,那就错了。

它是Microsoft对一个不太知名的PM(Presentation Model)模式的称呼 - 你可能需要阅读其描述。


1
是的。感谢您回答问题#3。那么关于问题1和2呢?我已经了解了Presentation Model,但不是非常清楚。能否请您回答我的问题1和2呢?谢谢。 - Mark
不和是的。我真的看不出在这里复制粘贴MSDN的意义。 - ima

1
在MVP和MVVM之间最重要的区别之一是,在MVP中存在紧密耦合,即接口的Presenter持有对View的引用,而在MVVM中,ViewModel没有持有对View的引用。
第二个区别是MVP是视图和Presenter之间的一对一关系,而MVVM是一对多关系。这意味着,我们可以使用单个ViewModel与许多不同的视图配对,但在MVP中,Presenter与单个视图绑定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接