十九、中介者模式

文章目录

  • [1 基本介绍](#1 基本介绍)
  • [2 案例](#2 案例)
    • [2.1 Developer 抽象类](#2.1 Developer 抽象类)
    • [2.2 FrontendDeveloper 类](#2.2 FrontendDeveloper 类)
    • [2.3 BackendDeveloper 类](#2.3 BackendDeveloper 类)
    • [2.4 Mediator 接口](#2.4 Mediator 接口)
    • [2.5 ProjectManager 类](#2.5 ProjectManager 类)
    • [2.6 Client 类](#2.6 Client 类)
    • [2.7 Client 类的运行结果](#2.7 Client 类的运行结果)
    • [2.8 总结](#2.8 总结)
  • [3 各角色之间的关系](#3 各角色之间的关系)
    • [3.1 角色](#3.1 角色)
      • [3.1.1 Colleague ( 同事 )](#3.1.1 Colleague ( 同事 ))
      • [3.1.2 ConcreteColleague ( 具体的同事 )](#3.1.2 ConcreteColleague ( 具体的同事 ))
      • [3.1.3 Mediator ( 中介者 )](#3.1.3 Mediator ( 中介者 ))
      • [3.1.4 ConcreteMediator ( 具体的中介者 )](#3.1.4 ConcreteMediator ( 具体的中介者 ))
      • [3.1.5 Client ( 客户端 )](#3.1.5 Client ( 客户端 ))
    • [3.2 类图](#3.2 类图)
  • [4 注意事项](#4 注意事项)
  • [5 在框架中的使用](#5 在框架中的使用)
  • [6 优缺点](#6 优缺点)
  • [7 适用场景](#7 适用场景)
  • [8 总结](#8 总结)

1 基本介绍

中介者模式 (Mediator Pattern)是一种 行为型 设计模式,它降低了多个对象和类之间的 通信复杂性 ,通过引入一个中介对象来 封装 一系列对象之间的 交互使得这些对象不需要直接相互引用

2 案例

本案例让甲方将需求告知项目经理,然后项目经理将需求分发给前、后端开发人员,前、后端开发人员负责根据需求修改各自负责的代码。

2.1 Developer 抽象类

java 复制代码
public abstract class Developer { // 开发人员
    // 由于其子类的逻辑十分简单,无需向 mediator 发送消息,所以其子类没有直接使用 mediator
    protected Mediator mediator; // 对应的中介者

    public Developer(Mediator mediator) {
        this.mediator = mediator;
    }

    protected abstract void modifyCode(String require); // 根据需求修改代码
}

2.2 FrontendDeveloper 类

java 复制代码
public class FrontendDeveloper extends Developer { // 前端开发人员
    public FrontendDeveloper(Mediator mediator) {
        super(mediator);
    }

    @Override
    protected void modifyCode(String require) {
        System.out.println("前端开发人员根据需求「" + require + "」修改前端显示的代码");
    }
}

2.3 BackendDeveloper 类

java 复制代码
public class BackendDeveloper extends Developer { // 后端开发人员
    public BackendDeveloper(Mediator mediator) {
        super(mediator);
    }

    @Override
    protected void modifyCode(String require) {
        System.out.println("后端开发人员根据需求「" + require + "」修改前端显示的代码");
    }
}

2.4 Mediator 接口

java 复制代码
// 实现这个接口后,可以当项目的中介者,接收甲方的需求,通知前、后端开发人员修改代码
public interface Mediator {
    void organizeMembers(); // 组织开发组的成员
    void changeRequire(String require); // 甲方更改需求
}

2.5 ProjectManager 类

java 复制代码
public class ProjectManager implements Mediator { // 项目经理
    // 假设项目中只需要一个前端开发人员和一个后端开发人员
    private FrontendDeveloper frontendDeveloper;
    private BackendDeveloper backendDeveloper;

    @Override
    public void organizeMembers() {
        // 组织了两个开发人员进行开发
        frontendDeveloper = new FrontendDeveloper(this);
        backendDeveloper = new BackendDeveloper(this);
    }

    @Override
    public void changeRequire(String require) {
        System.out.println("项目经理收到甲方更改的需求「" + require + "」");
        frontendDeveloper.modifyCode(require);
        backendDeveloper.modifyCode(require);
    }
}

2.6 Client 类

java 复制代码
public class Client { // 客户端,充当甲方,测试了项目经理更改需求的能力
    public static void main(String[] args) {
        Mediator pm = new ProjectManager();
        pm.organizeMembers();

        pm.changeRequire("增加一个 傻瓜式引导 的功能");
        pm.changeRequire("增加一个 个性化内容推荐 的功能");
    }
}

2.7 Client 类的运行结果

项目经理收到甲方更改的需求「增加一个 傻瓜式引导 的功能」
前端开发人员根据需求「增加一个 傻瓜式引导 的功能」修改前端显示的代码
后端开发人员根据需求「增加一个 傻瓜式引导 的功能」修改前端显示的代码
项目经理收到甲方更改的需求「增加一个 个性化内容推荐 的功能」
前端开发人员根据需求「增加一个 个性化内容推荐 的功能」修改前端显示的代码
后端开发人员根据需求「增加一个 个性化内容推荐 的功能」修改前端显示的代码

2.8 总结

在本案例中,甲方更改需求时,只需要通知项目经理即可,无需通知具体的开发人员,通知具体开发人员的任务由项目经理完成。此外,前后端开发人员员也不需要向对方提问应该如何达成需求,由项目经理来通知他们应该达成什么样的需求。这样就减少了对象之间的交流,只存在必要的交流,简化了对象之间的关系。

3 各角色之间的关系

3.1 角色

3.1.1 Colleague ( 同事 )

该角色负责 定义与 Mediator 角色进行通信的 接口 。本案例中,Developer 抽象类扮演了该角色。

3.1.2 ConcreteColleague ( 具体的同事 )

该角色负责 实现 Colleague 角色定义的 接口 。本案例中,FrontendDeveloper, BackendDeveloper 类都在扮演该角色。

3.1.3 Mediator ( 中介者 )

该角色负责 定义 创建 ConcreteColleague 角色的 接口 和 与其进行通信的 接口 。本案例中,Mediator 接口扮演了该角色。

3.1.4 ConcreteMediator ( 具体的中介者 )

该角色负责 实现 Mediator 角色的接口 。本案例中,ProjectManager 类扮演了该角色。

3.1.5 Client ( 客户端 )

该角色负责 创建 ConcreteMediator 角色的对象 ,并 使用它完成具体的业务逻辑 。本案例中,Client 类扮演了该角色。

3.2 类图

说明:

  • Colleague 中的 controlColleague() 方法用于与 Mediator 通信,根据 Mediator 的指示修改自己的状态。
  • Mediator 可以是接口。
  • Colleague 也可以是接口,不过需要将其聚合的 Mediator 放到所有 ConcreteColleague 中。
  • 当 Colleague 是抽象类时,其 setMediator() 方法可以由构造器替换。

4 注意事项

  • 中介者责任重大 :中介者对象承担了较多的责任,它是所有对象之间通信的桥梁。因此,一旦中介者出现了问题,整个系统就可能受到影响。所以,在设计中介者时,需要确保其 稳定性可靠性
  • 避免中介者对象复杂化 :如果设计不当,中介者对象可能会变得过于复杂,难以理解和维护。在实际使用中,需要 特别注意中介者的设计避免其承担过多的责任和功能。可以通过合理划分中介者的职责、采用模块化设计等方法来降低其复杂度。
  • 系统灵活性的保持 :虽然中介者模式提高了系统的灵活性,但 在设计时需要确保系统仍然能够应对未来的变化 。例如,可以通过定义 可扩展的中介者接口 、使用 策略模式 等方法来增强系统的可扩展性。
  • 性能考虑 :在某些情况下,通过中介者进行 间接交互 可能比 直接交互 具有更高的性能开销。因此,在设计完成后,需要对系统的性能进行测试,并根据测试结果进行优化。例如,可以通过优化中介者的内部实现、减少不必要的通信等方法来提高系统性能。

5 在框架中的使用

在流行的 Java 框架中,使用了中介者模式的思想:

  • MVC 框架 :在 MVC(Model-View-Controller)框架 中,控制器 (Controller)充当了 模型 (Model)和 视图(View)之间的中介者。控制器负责接收用户的输入,并将其转换为模型可以理解的格式,同时,当模型状态发生变化时,控制器也会负责通知视图进行更新。这种设计使得模型、视图和控制器之间的耦合度降低,提高了系统的可维护性和可扩展性。
  • 消息中间件 :在分布式系统中,消息中间件(如 RabbitMQ、Kafka 等)也体现了中介者模式的思想。消息中间件 作为消息的 生产者消费者 之间的中介,负责消息的存储和转发,使得生产者和消费者之间不需要直接进行通信,从而降低了系统的耦合度,提高了系统的可靠性和可扩展性。

6 优缺点

优点

  • 解耦与结构转换多个类相互耦合 容易形成 网状结构 ,复杂且难以维护。使用中介者模式可以将 网状结构 分离为 星型结构,通过中介者对象进行通信,从而实现解耦。
  • 符合迪米特法则(降低对象间的耦合度) :中介者模式使得 对象之间不需要知道彼此的具体实现细节 ,只需通过中介者进行通信,这符合 迪米特法则 ,有助于减少对象之间的 耦合度。这使得对象之间的依赖关系更加简单,系统的结构更加清晰。
  • 易于扩展和维护 :当系统中需要增加新的对象或改变对象之间的交互方式时,只需修改中介者对象即可,而无需修改其他对象,这降低了系统 扩展维护 的复杂性。
  • 提高系统的灵活性 :通过更换不同的中介者对象,可以灵活地改变对象之间的交互逻辑,从而增加系统的 灵活性

缺点

  • 中介者可能变得复杂:如果系统中存在大量的对象,并且这些对象之间的交互关系非常复杂,那么中介者对象可能会变得非常庞大和复杂。这会增加中介者对象的维护难度,并可能导致代码难以理解和修改。
  • 对中介者的依赖 :由于 所有对象之间的交互都通过中介者进行 ,因此 系统对中介者的依赖程度较高。如果中介者出现故障或设计不当,可能会影响整个系统的正常运行。
  • 可能隐藏系统复杂性 :中介者模式可能会 隐藏对象之间的 直接交互关系,使得系统的整体结构和交互逻辑变得不够直观。这可能会给开发人员带来一定的理解难度,尤其是在处理复杂的系统时。
  • 更高的性能开销 :在某些情况下,通过中介者进行 间接交互 可能比 直接交互 具有 更高的性能开销。虽然这种开销在大多数情况下是可以接受的,但在性能敏感的应用中可能需要谨慎考虑。

7 适用场景

  • 引用关系复杂的系统
    • 系统中对象之间存在复杂的引用关系 ,且 这些引用关系导致系统结构混乱、难以理解 时,可以考虑使用中介者模式。通过引入中介者对象,可以封装对象之间的交互细节,降低系统的复杂度。
    • 例如,在 电商平台 中,卖家、买家、物流公司和支付平台之间可能存在复杂的交互关系,可以通过增加一个"消费中介"来分离它们之间的关系。
  • 需要改变行为的系统
    • 如果 系统中对象之间的交互行为需要频繁变更 ,且 这些变更会影响到多个对象 时,可以使用中介者模式。通过增加新的中介者类,可以轻松地实现行为的扩展和变更,而无需修改原有对象。
    • 例如,在 多人聊天室场景 中,如果需要变更消息的传递方式(如从文本消息变为语音消息),可以通过增加一个新的中介者类来实现,而无需修改用户对象。
  • 高耦合的系统
    • 系统中对象之间的耦合度较高 ,且 这种耦合度影响了系统的可维护性和可扩展性 时,可以考虑使用中介者模式。通过中介者对象来封装对象之间的交互,可以降低对象之间的耦合度,使系统更加灵活和易于维护。
    • 例如,在 MVC 框架中,控制器(Controller)作为模型(Model)和视图(View)之间的中介者,降低了它们之间的耦合度。当需要修改视图或模型的实现时,只需修改控制器即可,而无需修改其他组件。
  • 集中化交互管理的系统
    • 在某些场景中,可能 需要一个中心化的对象来管理多个对象之间的交互。此时,可以使用中介者模式来实现。中介者对象负责接收来自各个对象的请求,并根据一定的规则将这些请求转发给相应的对象进行处理。
    • 例如,在交通控制系统中,交通灯可以作为中介者对象来管理车辆和行人的交互。交通灯根据当前的道路情况和交通规则来控制车辆和行人的通行。

8 总结

中介者模式 是一种 行为型 设计模式,它通过引入 中介 ,组织了系统中各个对象之间的关系,从 网状关系 简化到 星型关系,降低了系统的耦合度,提高了系统的灵活性。不过,给对象之间添加一个中介会导致性能的下降,如果对性能要求很高,最好不要使用本模式。

相关推荐
litGrey15 分钟前
Maven国内镜像(四种)
java·数据库·maven
丶白泽41 分钟前
重修设计模式-结构型-桥接模式
java·设计模式·桥接模式
o独酌o1 小时前
递归的‘浅’理解
java·开发语言
无问8171 小时前
数据结构-排序(冒泡,选择,插入,希尔,快排,归并,堆排)
java·数据结构·排序算法
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS在线文档管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
Flying_Fish_roe2 小时前
Spring Boot-版本兼容性问题
java·spring boot·后端
程序猿进阶2 小时前
如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?
java·ide·vscode·算法·面试·职场和发展·架构
slandarer2 小时前
MATLAB | R2024b更新了哪些好玩的东西?
java·数据结构·matlab
南郁2 小时前
把设计模式用起来!(3)用不好模式?之时机不对
设计模式
Dola_Pan2 小时前
Linux文件IO(一)-open使用详解
java·linux·dubbo