1. 概述

在本教程中,我们将了解模型视图控制器和模型视图呈现器模式。我们还将讨论它们之间的差异。

2. 设计模式和架构模式

2.1.架构模式

架构模式是针对软件架构中常见问题的通用、可重用的解决方案。这些对代码库有广泛的影响。

例如,这些会水平或垂直地影响软件。水平方向是指如何构建层内的代码。相反,垂直意味着如何从外层到内层处理请求并返回。

一些更常见的架构模式是 MVCMVPMVVM

2.2.设计模式

设计模式通常与代码级共性相关。他们提供了各种用于改进和构建较小子系统的方案。

此外,设计模式是一种中等规模的策略,可以充实实体及其关系的一些结构和行为。一些常用的设计模式是单例模式工厂模式构建器模式。

设计模式与架构模式的不同之处在于它们的范围 。它们更加本地化,对代码库的影响较小。相反,它们仅影响代码库的特定部分。在下一节中,我们将讨论为什么使用这些模式。

3. 为什么选择 MVC 和 MVP 模式

使用这些模式背后的主要思想是 业务层和 UI 层之间的 关注点分离 。这些模式为我们提供了易于测试等功能。他们还隐藏数据访问。

我们可以说,通过隔离主要组件,它们更能适应变化。然而,最大的缺点是增加了复杂性和学习曲线。

4.MVC模式

在 MVC 模式中,功能根据三个独立的关注点分为三个组件。首先, 视图负责渲染UI元素 。其次, 控制器响应 UI 操作该模型处理业务行为和状态管理

在大多数实现中,所有三个组件都可以直接相互交互。然而,在一些实现中,控制器负责确定要显示哪个视图。

下图显示了 MVC 的控制流程:

MVC模式

该模型代表整个业务逻辑层。视图表示从模型中获取的数据。此外,它还处理表示逻辑。最后,控制器处理控制流逻辑并更新模型。

MVC 没有指定视图和模型的内部结构 。通常,视图层在单个类中实现。

然而,在这种情况下, 可能会出现一些问题

  • 视图和模型紧密耦合。因此,视图的功能需求很容易渗透到模型中并污染业务逻辑层
  • 视图是整体的,通常与 UI 框架紧密耦合。因此,对视图进行单元测试变得很困难

5.MVP模式

MVP 模式是基于 MVC 模式概念的 UI 表示模式。但是,它没有指定如何构建整个系统。 它仅规定如何构建视图

该模式通常将职责划分为四个组件。首先, 视图负责渲染 UI 元素 。其次,视图接口用于将演示者与其视图松散耦合。

最后, Presenter与视图和模型进行交互,模型负责业务行为和状态管理

在一些实现中,呈现器与服务(控制器)层交互以检索/保留模型。视图接口和服务层通常用于使为呈现器和模型编写单元测试变得更容易。

下图展示了 MVP 的控制流程:

mvp_模式

该模型与 MVC 中的相同,包含业务逻辑。视图是显示数据的被动接口。它将用户操作发送给演示者。

演示者坐在模型和视图之间。它触发业务逻辑并使视图能够更新。它从模型接收数据并在视图中显示相同的数据。这使得测试演示者变得更加容易。

尽管如此, MVP 仍然存在一些问题

  • 控制器经常被省略。由于缺少控制器,控制流也必须由演示者处理。这使得演示者负责两个问题:更新模型和演示模型
  • 我们不能使用数据绑定。如果可以与 UI 框架进行绑定,我们应该利用它来简化演示者

6.MVC和MVP的实现

我们将通过一个简单的示例来理解这些模式。我们有一个需要展示和更新的产品。这些操作在 MVC 和 MVP 中的处理方式不同。

6.1.视图类

我们有一个简单的视图类,用于输出产品详细信息。 MVP 和 MVC 的视图类是相似的:

public class ProductView {
    public void printProductDetails(String name, String description, Double price) {
        log.info("Product details:");
        log.info("product Name: " + name);
        log.info("product Description: " + description);
        log.info("product price: " + price);
    }
}

6.2. MVP 模型和演示者类

现在让我们为 MVP 定义一个仅负责业务逻辑的 Product 类:

public class Product {
    private String name;
    private String description;
    private Double price;
    
   //getters & setters
}

MVP 中的 Presenter 类从模型中获取数据并将其传递给视图:

public class ProductPresenter {
    private final Product product;
    private final ProductView view;
    
     //getters,setters & constructor
    
    public void showProduct() {
        productView.printProductDetails(product.getName(), product.getDescription(), product.getPrice());
    }
}

6.3. MVC模型类

对于 MVC 来说,不同之处在于 视图将从模型类而不是 MVP 中的演示者类获取数据

我们可以为MVC定义一个模型类:

public class Product {
    private String name;
    private String description;
    private Double price;
    private ProductView view;
    
    //getters,setters
    
    public void showProduct() {
        view.printProductDetails(name, description, price);
    }
}

注意 showProduct() 方法 。此方法处理从模型到视图传递的数据。在 MVP 中,这是在演示者类中完成的,而在 MVC 中,这是在模型类中完成的。

7.MVC与MVP的比较

MVC 和 MVP 之间没有太多区别。这两种模式都侧重于分离多个组件的责任,从而促进 UI(视图)与业务层(模型)的松散耦合。

主要区别在于模式的实现方式以及在某些高级场景中的实现方式。让我们看一下 一些主要差异

  • 耦合性:视图和模型在 MVC 中是紧耦合的,但在 MVP 中是松耦合的
  • 通信:在 MVP 中,View-Presenter 和 Presenter-Model 之间的通信通过接口进行。然而,MVC 中控制器和视图层属于同一个 Activity/Fragment
  • 用户输入:在 MVC 中,用户输入由 控制器 处理 ,指示模型进行进一步操作。但 在 MVP 中, 用户输入 由视图处理 ,指示演示者调用适当的函数
  • 关系类型: 控制器和视图之间存在 多对一 关系 。一个Controller可以根据MVC中所需的操作选择不同的视图。另一方面,在 MVP 中,演示者和视图具有一对一的关系,其中一个演示者类一次管理一个视图
  • 主要组件:在MVC中,控制器负责。它根据用户的请求创建适当的视图并与模型交互。相反,在 MVP 中,观点才是主导。演示者上的视图调用方法,进一步指导模型
  • 单元测试:由于紧密耦合,MVC 对单元测试的支持有限。另一方面,MVP 很好地支持单元测试

8. 为什么 MVP 比 MVC 更有优势

MVP 比 MVC 稍占优势,因为它可以将我们的应用程序分解为模块。因此,我们可以避免不断创建视图。换句话说,MVP 可以帮助我们的视图可重用。

9. 结论

在本教程中,我们了解了 MVC 和 MVP 架构模式以及它们之间的比较。

示例代码可在 GitHub 上获取。