前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

一、中介者模式(Mediator Pattern

1. 模式概述

中介者模式 是一种 行为型设计模式,它用一个 中介对象(Mediator) 来封装一系列对象之间的交互。 对象之间不再直接相互引用,而是通过中介者进行通信,从而 降低耦合度,使系统更易于维护和扩展。

核心思想“多对多 → 一对多” —— 所有交互经由中介协调。

中介者模式 = 解耦通信 + 集中协调

  • 它不是“增加一层”,而是“重构关系”——将混乱的网状依赖,转化为清晰的星型结构。

类比理解:混乱的开发小组

  • 成员 A 直接指挥 B,B 又质问 C,C 反过来改 A 的代码……沟通爆炸,效率低下;
  • 引入 技术负责人(中介者) 后,所有人只向他汇报,由他统一调度——沟通路径从 N² 降为 N

2. 使用场景

中介者模式适用于以下情况:

  • 一组对象 以复杂方式紧密耦合,难以复用;
  • 对象之间的通信逻辑 分散在多个类中,导致维护困难;
  • 需要 定制或重用对象间协作行为,而不修改对象本身;
  • 系统中存在 大量“多对多”依赖,希望简化为“星型”结构。

典型应用

  • GUI 组件交互(按钮点击影响文本框、下拉框等);
  • 聊天室系统(用户不直接发消息给彼此,而是发给聊天室);
  • 游戏中的事件总线(角色死亡 → 触发音效 + 计分 + UI 更新);
  • 微服务间的协调器(Saga 模式中的 Orchestrator)。

3. 示例程序:设备控制系统(优化版)

1)同事抽象类 Device

/**
 * 同事类(Colleague)
 * 所有设备的基类,持有中介者引用
 */
public abstract class Device {
    protected DeviceMediator mediator;

    public Device(DeviceMediator mediator) {
        this.mediator = mediator;
    }

    // 设备开启(通知中介者)
    public void turnOn() {
        System.out.println(this.getClass().getSimpleName() + " 开启");
        onTurnedOn(); // 子类可扩展
    }

    // 设备关闭(由中介者调用)
    public void turnOff() {
        System.out.println(this.getClass().getSimpleName() + " 关闭");
        onTurnedOff(); // 子类可扩展
    }

    // 钩子方法(供子类重写)
    protected void onTurnedOn() {}
    protected void onTurnedOff() {}
}

2)具体同事类

a、A 设备

public class ADevice extends Device {
    public ADevice(DeviceMediator mediator) {
        super(mediator);
    }

    // A 开启时,通知中介者协调其他设备
    @Override
    protected void onTurnedOn() {
        mediator.coordinateOnA(this);
    }
}

b、B 设备

public class BDevice extends Device {
    public BDevice(DeviceMediator mediator) {
        super(mediator);
    }
}

c、C 设备

public class CDevice extends Device {
    public CDevice(DeviceMediator mediator) {
        super(mediator);
    }
}

3)中介者接口 DeviceMediator

/**
 * 中介者接口(Mediator)
 */
public interface DeviceMediator {
    void coordinateOnA(ADevice aDevice);
    // 可扩展:coordinateOnB, handleEmergency 等
}

4)具体中介者 DeviceController

/**
 * 具体中介者(ConcreteMediator)
 * 协调所有设备的交互逻辑
 */
public class DeviceController implements DeviceMediator {
    private final ADevice aDevice;
    private final BDevice bDevice;
    private final CDevice cDevice;

    public DeviceController(ADevice a, BDevice b, CDevice c) {
        this.aDevice = a;
        this.bDevice = b;
        this.cDevice = c;
    }

    @Override
    public void coordinateOnA(ADevice aDevice) {
        System.out.println("【中介者】检测到 A 开启,正在关闭 B 和 C...");
        bDevice.turnOff();
        cDevice.turnOff();
    }

    // 可扩展其他协调逻辑
}

5)客户端测试 Main

  • 设备之间 零直接依赖
  • 交互逻辑 集中管理,易于修改(如改为“开启 A 时只关 B”);
  • 新增设备(如 D)只需注册到中介者,不影响现有代码
/**
 * 客户端(Client)
 */
public class Main {
    public static void main(String[] args) {
        // 创建中介者
        DeviceController mediator = new DeviceController(null, null, null);

        // 创建设备(注入中介者)
        ADevice a = new ADevice(mediator);
        BDevice b = new BDevice(mediator);
        CDevice c = new CDevice(mediator);

        // 修复引用(避免构造时循环依赖)
        mediator = new DeviceController(a, b, c);
        a.mediator = mediator;
        b.mediator = mediator;
        c.mediator = mediator;

        // 触发 A 开启
        a.turnOn();
    }
}

输出:

ADevice 开启
【中介者】检测到 A 开启,正在关闭 B 和 C...
BDevice 关闭
CDevice 关闭

6) 模式角色

  • 同事对象 不持有彼此的引用,只持有 中介者引用
  • 所有跨对象调用 必须经过中介者
角色 职责 示例
Mediator(中介者接口) 定义同事对象与中介者通信的接口 DeviceMediator
ConcreteMediator(具体中介者) 实现中介者接口,协调各同事对象的交互 DeviceController
Colleague(同事抽象类/接口) 定义同事对象的公共行为,持有中介者引用 Device
ConcreteColleague(具体同事) 实现具体业务逻辑,通过中介者与其他同事通信 ADevice, BDevice, CDevice
                ┌───────────────────┐
                │   DeviceMediator  │
                │-------------------│
                │ + coordinateOnA() │
                └─────────▲─────────┘
                          │
        ┌─────────────────┴─────────────────┐
        │                                   │
┌───────▼───────┐               ┌───────────▼────────────┐
│    Device     │               │   DeviceController     │
│---------------│               │------------------------│
│ - mediator    │               │ - aDevice: ADevice     │
│ + turnOn()    │               │ - bDevice: BDevice     │
│ + turnOff()   │               │ - cDevice: CDevice     │
└───────▲───────┘               └───────────┬────────────┘
        │                                   │
  ┌─────┴─────┐                    ┌────────┴─────────┐
  │ ADevice   │                    │ BDevice / CDevice│
  └───────────┘                    └──────────────────┘

4、FQA

1)模式优点

  • 降低耦合度:同事类之间无直接依赖;
  • 集中控制交互逻辑:便于修改、复用、测试;
  • 符合迪米特法则:对象只与“朋友”(中介者)通信;
  • 提升模块独立性:同事类可单独替换或扩展。

2)注意事项

  • 中介者可能膨胀:若交互逻辑复杂,中介者会变得庞大难维护;
  • 过度设计风险:简单交互无需引入中介者;
  • 调试难度增加:请求流转路径不直观;
  • 需谨慎处理初始化顺序(如循环依赖)。