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

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

技术背景

在软件开发中,为了实现代码的模块化、可维护性和可测试性,人们设计了许多架构模式。MVP(Model - View - Presenter)和MVC(Model - View - Controller)就是其中两种常见的架构模式,它们都旨在分离业务逻辑和展示逻辑,提高软件的可维护性和可扩展性。

实现步骤

MVP模式

  • 模型(Model):负责处理数据和业务逻辑。
  • 视图(View):是一个接口,用于显示数据并将用户命令(事件)路由到Presenter。视图通常持有对Presenter的引用,但不包含逻辑。
  • Presenter:作为视图和模型之间的“中间人”,持有对视图和模型的引用。Presenter负责将模型绑定到视图,并处理用户交互的逻辑。

两种主要变体

  • 被动视图(Passive View):视图尽可能简单,几乎不包含逻辑。Presenter是与视图和模型进行交互的中间人,视图和模型完全相互屏蔽。模型可以触发事件,但Presenter订阅这些事件以更新视图。在被动视图中没有直接的数据绑定,而是视图暴露了Presenter用于设置数据的setter属性,所有状态都由Presenter管理。
    • 优点:可测试性高,视图和模型分离清晰。
    • 缺点:需要更多的工作,例如手动进行所有的数据绑定。
  • 监督控制器(Supervising Controller):Presenter处理用户手势,视图通过数据绑定直接绑定到模型。Presenter的工作是将模型传递给视图,以便视图可以进行绑定。Presenter还包含处理按钮点击、导航等手势的逻辑。
    • 优点:通过利用数据绑定减少了代码量。
    • 缺点:可测试性降低(由于数据绑定),并且视图的封装性较差,因为它直接与模型通信。

MVC模式

  • 模型(Model):处理数据和业务逻辑。
  • 视图(View):负责处理图形用户界面对象和展示,通常是无状态的,不包含逻辑。
  • 控制器(Controller):负责根据用户的操作决定显示哪个视图。控制器接收视图的操作请求,处理业务逻辑,并返回正确的视图。

核心代码

MVP模式示例(Passive View变体)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 视图接口
public interface ICustomerView
{
string Name { get; set; }
}

// 视图实现
public class CustomerView : ICustomerView
{
public string Name
{
get { return txtName.Text; }
set { txtName.Text = value; }
}
}

// Presenter类
public class CustomerPresenter
{
private readonly ICustomerView _view;
private readonly CustomerModel _model;

public CustomerPresenter(ICustomerView view, CustomerModel model)
{
_view = view;
_model = model;
UpdateView();
}

private void UpdateView()
{
_view.Name = _model.Name;
}
}

// 模型类
public class CustomerModel
{
public string Name { get; set; }
}

MVC模式示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 模型类
class ProductModel:
def __init__(self, name, price):
self.name = name
self.price = price

# 视图类
class ProductView:
def display_product(self, product):
print(f"Product: {product.name}, Price: {product.price}")

# 控制器类
class ProductController:
def __init__(self, model, view):
self.model = model
self.view = view

def show_product(self):
self.view.display_product(self.model)

# 使用示例
product = ProductModel("Apple", 2.5)
view = ProductView()
controller = ProductController(product, view)
controller.show_product()

最佳实践

  • MVP模式:适用于需要高可测试性和视图与模型松散耦合的场景,例如大型项目或需要频繁进行单元测试的项目。在开发过程中,可以先编写Presenter和模型的单元测试,然后再实现视图。
  • MVC模式:适用于需要根据用户操作动态切换视图的场景,例如Web应用程序。在Web应用中,控制器可以根据URL请求来决定显示哪个视图。

常见问题

  • MVP和MVC的区别是什么?
    • 控制流不同:在MVP中,视图是主导,每个视图调用其Presenter或有Presenter监听的事件;在MVC中,控制器是主导,根据事件/请求来管理视图。
    • 视图状态不同:MVP中的视图可以是有状态的,而MVC中的视图通常是无状态的。
    • 视图逻辑不同:MVP中的视图应尽量简单,不包含逻辑;MVC中的视图可能包含一些逻辑。
    • 可测试性:MVP更容易进行单元测试,因为Presenter与视图通过接口交互,可以模拟视图。
    • 视图与模型的关系:MVP中视图与模型完全隔离,由Presenter负责绑定;MVC中视图可以与模型通信。
  • 如何选择MVP和MVC模式?
    • 如果团队熟悉Web Forms开发,并且项目对可测试性和视图与模型的解耦要求较高,可以选择MVP模式。
    • 如果项目需要根据用户操作动态切换视图,并且对控制器的集中管理有需求,可以选择MVC模式。
    • 一般来说,MVP适用于大型项目,MVC适用于小型项目。但这并不是绝对的,还需要根据项目的具体需求和团队的技术栈来决定。

什么是MVP和MVC,它们有什么区别?
https://119291.xyz/posts/2025-05-15.what-are-mvp-and-mvc-and-what-is-the-difference/
作者
ww
发布于
2025年5月15日
许可协议