设计模式之简单化_Mediator中介者模式_只有一个仲裁者
前言
Github:https://github.com/HealerJean
一、中介者模式(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)注意事项
- 中介者可能膨胀:若交互逻辑复杂,中介者会变得庞大难维护;
- 过度设计风险:简单交互无需引入中介者;
- 调试难度增加:请求流转路径不直观;
- 需谨慎处理初始化顺序(如循环依赖)。


