中介者模式
中介者模式:解耦复杂交互的设计智慧
一、中介者模式的定义与核心思想
中介者模式(Mediator Pattern) 是一种行为型设计模式,其核心思想是通过引入一个 “中介者” 对象,封装多个对象之间的复杂交互逻辑,使原本相互耦合的对象不再直接通信,而是通过中介者间接交互。这一模式遵循 “迪米特法则”(最少知识原则),旨在降低对象间的耦合度,提高系统的可维护性和扩展性。
简单来说,中介者模式就像现实中的 “项目经理”—— 团队成员无需直接沟通协调任务,只需向项目经理汇报进度、提出需求,由项目经理统一分配资源、协调工作,避免了成员间的混乱交互。在软件系统中,当多个对象存在多对多依赖关系时,中介者模式能将复杂的网状依赖转化为清晰的星状结构(中介者为中心,其他对象为节点)。
二、中介者模式的核心结构
中介者模式包含以下 4 个关键角色,各角色职责明确、协同工作:
-
抽象中介者(Mediator):定义中介者与各个同事对象交互的接口,通常包含注册同事对象、转发同事请求的抽象方法。
-
具体中介者(ConcreteMediator):实现抽象中介者的接口,维护所有同事对象的引用,封装具体的交互逻辑。当收到某个同事的请求时,会根据业务规则协调其他相关同事做出响应。
-
抽象同事类(Colleague):定义同事对象的公共接口,包含一个指向中介者对象的引用(确保同事能通过中介者通信),以及发送请求、接收响应的抽象方法。
-
具体同事类(ConcreteColleague):实现抽象同事类的接口,当自身状态变化或需要交互时,不会直接通知其他同事,而是通过中介者传递信息;同时接收中介者转发的其他同事的请求并做出处理。
三、中介者模式的工作原理
中介者模式的交互流程可概括为 3 步:
-
注册阶段:所有具体同事对象在初始化时,将自身引用注册到具体中介者中,使中介者能管理所有同事。
-
请求传递:当某个同事需要与其他同事交互时,不会直接调用其他同事的方法,而是调用自身的 “发送请求” 方法,将请求传递给中介者。
-
中介协调:具体中介者收到请求后,根据预设的业务逻辑,判断需要通知哪些其他同事,并调用这些同事的 “接收响应” 方法,完成交互。
四、实际场景案例:电商订单支付流程
以电商平台的 “订单支付 - 库存扣减 - 物流创建” 流程为例,未使用中介者模式时,订单系统、库存系统、物流系统会直接相互调用,形成复杂耦合(订单支付后需调用库存扣减,库存扣减成功后需调用物流创建);使用中介者模式后,流程如下:
1. 角色定义
-
抽象中介者(OrderMediator):定义注册系统、协调流程的接口。
-
具体中介者(OrderProcessMediator):维护订单、库存、物流系统的引用,封装 “支付 - 扣库存 - 创物流” 的逻辑。
-
抽象同事类(SystemColleague):包含中介者引用,定义发送请求、接收响应的方法。
-
具体同事类:订单系统(OrderSystem)、库存系统(InventorySystem)、物流系统(LogisticsSystem)。
2. 交互流程
-
订单系统(OrderSystem)接收用户支付请求后,不直接调用库存系统,而是通过中介者发送 “支付成功” 请求。
-
具体中介者(OrderProcessMediator)收到请求后,先调用库存系统的 “扣减库存” 方法。
-
库存系统执行扣减后,通过中介者返回 “库存充足,扣减成功” 响应。
-
中介者继续调用物流系统的 “创建物流单” 方法,完成整个流程。
-
若库存不足,中介者会通知订单系统触发 “支付退款” 流程,无需订单系统直接判断库存状态。
3. 完整可运行代码实现
(1)抽象中介者(OrderMediator)
/**
* 抽象中介者:定义中介者与同事对象的交互接口
*/
public interface OrderMediator {
// 注册同事对象
void registerColleague(SystemColleague colleague);
// 处理同事对象的请求
void handleRequest(SystemColleague sender, String request);
}
(2)具体中介者(OrderProcessMediator)
/**
* 具体中介者:封装订单支付-库存扣减-物流创建的核心逻辑
*/
public class OrderProcessMediator implements OrderMediator {
// 维护所有同事对象的引用(订单、库存、物流系统)
private OrderSystem orderSystem;
private InventorySystem inventorySystem;
private LogisticsSystem logisticsSystem;
@Override
public void registerColleague(SystemColleague colleague) {
// 注册时区分同事对象类型,赋值给对应引用
if (colleague instanceof OrderSystem) {
this.orderSystem = (OrderSystem) colleague;
} else if (colleague instanceof InventorySystem) {
this.inventorySystem = (InventorySystem) colleague;
} else if (colleague instanceof LogisticsSystem) {
this.logisticsSystem = (LogisticsSystem) colleague;
}
}
@Override
public void handleRequest(SystemColleague sender, String request) {
// 处理订单系统的“支付成功”请求
if (sender == orderSystem && "支付成功".equals(request)) {
System.out.println("中介者收到订单系统的请求:" + request);
// 1. 协调库存系统扣减库存
String inventoryResult = inventorySystem.deductStock();
// 2. 根据库存扣减结果,协调后续流程
if ("扣减成功".equals(inventoryResult)) {
// 库存充足:协调物流系统创建物流单
logisticsSystem.createLogisticsOrder();
// 通知订单系统向用户发送成功消息
orderSystem.receiveResponse("物流单已创建,订单完成");
} else {
// 库存不足:协调订单系统执行退款
orderSystem.refund();
// 通知订单系统向用户发送退款消息
orderSystem.receiveResponse("库存不足,已自动退款");
}
}
// 可扩展其他请求类型(如物流系统的“物流创建成功”通知)
else if (sender == logisticsSystem && "物流创建成功".equals(request)) {
System.out.println("中介者收到物流系统的通知:" + request);
orderSystem.receiveResponse("物流单号:LOG2024001,请注意查收");
}
}
}
(3)抽象同事类(SystemColleague)
/**
* 抽象同事类:定义所有系统(同事)的公共接口
*/
public abstract class SystemColleague {
// 持有中介者引用(所有同事都通过中介者通信)
protected OrderMediator mediator;
// 构造方法:初始化时自动注册到中介者
public SystemColleague(OrderMediator mediator) {
this.mediator = mediator;
this.mediator.registerColleague(this);
}
// 发送请求给中介者
public abstract void sendRequest(String request);
// 接收中介者转发的响应
public abstract void receiveResponse(String response);
}
(4)具体同事类:订单系统(OrderSystem)
/**
* 具体同事类:订单系统(负责处理支付、退款、通知用户)
*/
public class OrderSystem extends SystemColleague {
// 订单ID(模拟具体订单)
private String orderId;
public OrderSystem(OrderMediator mediator, String orderId) {
super(mediator);
this.orderId = orderId;
}
@Override
public void sendRequest(String request) {
System.out.println("订单系统[" + orderId + "]发送请求:" + request);
mediator.handleRequest(this, request);
}
@Override
public void receiveResponse(String response) {
System.out.println("订单系统[" + orderId + "]收到响应:" + response);
// 通知用户(模拟实际业务逻辑)
notifyUser(response);
}
// 退款逻辑
public void refund() {
System.out.println("订单系统[" + orderId + "]执行退款操作");
}
// 通知用户逻辑
private void notifyUser(String msg) {
System.out.println("【用户通知】订单[" + orderId + "]:" + msg + "n");
}
// Getter(供其他系统获取订单信息,按需提供)
public String getOrderId() {
return orderId;
}
}
(5)具体同事类:库存系统(InventorySystem)
/**
* 具体同事类:库存系统(负责扣减库存、检查库存状态)
*/
public class InventorySystem extends SystemColleague {
// 模拟库存(key:商品ID,value:库存数量)
private final Map<String,Integer> stockMap;
public InventorySystem(OrderMediator mediator) {
super(mediator);
// 初始化库存(模拟有货场景)
stockMap = new HashMap<>();
stockMap.put("PROD2024001", 10); // 商品ID:PROD2024001,库存10件
}
@Override
public void sendRequest(String request) {
System.out.println("库存系统发送请求:" + request);
mediator.handleRequest(this, request);
}
@Override
public void receiveResponse(String response) {
System.out.println("库存系统收到响应:" + response);
}
// 扣减库存(核心业务方法)
public String deductStock() {
String productId = "PROD2024001"; // 模拟订单对应的商品ID
int stock = stockMap.getOrDefault(productId, 0);
if (stock > 0) {
stockMap.put(productId, stock - 1);
System.out.println("库存系统:商品[" + productId + "]扣减1件,剩余库存:" + (stock - 1));
return "扣减成功";
} else {
System.out.println("库存系统:商品[" + productId + "]库存不足");
return "扣减失败";
}
}
}
(6)具体同事类:物流系统(LogisticsSystem)
/**
* 具体同事类:物流系统(负责创建物流单)
*/
public class LogisticsSystem extends SystemColleague {
public LogisticsSystem(OrderMediator mediator) {
super(mediator);
}
@Override
public void sendRequest(String request) {
System.out.println("物流系统发送请求:" + request);
mediator.handleRequest(this, request);
}
@Override
public void receiveResponse(String response) {
System.out.println("物流系统收到响应:" + response);
}
// 创建物流单(核心业务方法)
public void createLogisticsOrder() {
// 模拟创建物流单逻辑
String logisticsId = "LOG2024001";
System.out.println("物流系统:创建物流单成功,物流单号:" + logisticsId);
// 向中介者发送“物流创建成功”通知(可触发后续流程)
sendRequest("物流创建成功");
}
}
(7)测试类(MediatorTest)
/**
* 测试类:验证中介者模式的完整流程
*/
public class MediatorTest {
public static void main(String[] args) {
// 1. 创建具体中介者
OrderMediator mediator = new OrderProcessMediator();
// 2. 创建具体同事类(初始化时自动注册到中介者)
OrderSystem orderSystem = new OrderSystem(mediator, "ORDER2024001");
InventorySystem inventorySystem = new InventorySystem(mediator);
LogisticsSystem logisticsSystem = new LogisticsSystem(mediator);
// 3. 触发订单支付成功流程
System.out.println("=== 开始执行订单支付流程 ===");
orderSystem.sendRequest("支付成功");
// 4. 再次触发流程(验证库存扣减后的状态)
System.out.println("n=== 再次执行订单支付流程(验证库存剩余) ===");
orderSystem.sendRequest("支付成功");
}
}
4. 代码运行结果
=== 开始执行订单支付流程 ===
订单系统[ORDER2024001]发送请求:支付成功
中介者收到订单系统的请求:支付成功
库存系统:商品[PROD2024001]扣减1件,剩余库存:9
物流系统:创建物流单成功,物流单号:LOG2024001
物流系统发送请求:物流创建成功
中介者收到物流系统的通知:物流创建成功
订单系统[ORDER2024001]收到响应:物流单号:LOG2024001,请注意查收
【用户通知】订单[ORDER2024001]:物流单号:LOG2024001,请注意查收
=== 再次执行订单支付流程(验证库存剩余) ===
订单系统[ORDER2024001]发送请求:支付成功
中介者收到订单系统的请求:支付成功
库存系统:商品[PROD2024001]扣减1件,剩余库存:8
物流系统:创建物流单成功,物流单号:LOG2024001
物流系统发送请求:物流创建成功
中介者收到物流系统的通知:物流创建成功
订单系统[ORDER2024001]收到响应:物流单号:LOG2024001,请注意查收
【用户通知】订单[ORDER2024001]:物流单号:LOG2024001,请注意查收
五、中介者模式的优缺点
优点
-
降低耦合度:消除了同事对象间的直接依赖,将多对多耦合转化为中介者与同事的一对多耦合,便于系统维护。
-
集中控制交互:所有交互逻辑集中在中介者中,清晰可见,便于修改和扩展(如新增 “优惠券抵扣” 流程,只需修改中介者逻辑,无需改动同事类)。
-
简化对象职责:同事对象无需关注其他对象的交互细节,只需专注自身业务逻辑,符合 “单一职责原则”。
缺点
-
中介者膨胀风险:随着系统复杂度增加,中介者会封装越来越多的交互逻辑,可能导致中介者类过于庞大、难以维护(称为 “中介者反模式”)。
-
依赖集中:所有同事对象都依赖中介者,若中介者出现故障,整个系统的交互都会受影响,存在 “单点故障” 风险。
六、适用场景与使用建议
适用场景
-
多个对象存在复杂的多对多交互,导致对象间耦合严重,难以维护。
-
希望集中管理对象间的交互逻辑,便于统一修改和扩展。
-
系统中存在多个 “协调者” 角色,需避免协调逻辑分散在各个对象中。
使用建议
-
拆分复杂中介者:若中介者逻辑过于庞大,可将其拆分为多个细分中介者(如按业务模块拆分 “支付中介者”“物流中介者”),或结合其他模式(如策略模式)封装不同的交互策略。
-
避免过度使用:若对象间交互简单(仅一对一或少量依赖),无需引入中介者,否则会增加系统复杂度。
-
结合观察者模式:当同事对象状态变化需要通知多个其他同事时,可在中介者中整合观察者模式,简化通知逻辑。
七、与其他设计模式的区别
- 中介者模式 vs 观察者模式:
- 观察者模式是 “一对多” 的通知机制,焦点在 “状态变化通知”,观察者与被观察者无直接依赖,但交互逻辑分散在观察者中。
- 中介者模式是 “多对多” 的交互协调,焦点在 “复杂交互管理”,通过中介者集中控制,同事对象完全依赖中介者
- 中介者模式 vs 外观模式:
- 外观模式是为子系统提供统一的入口,简化子系统的调用,不改变子系统内部的交互逻辑。
- 中介者模式是改变子系统内部的交互方式,将分散的交互集中到中介者,降低子系统内部耦合。

浙公网安备 33010602011771号