中介者模式

中介者模式:解耦复杂交互的设计智慧

一、中介者模式的定义与核心思想

中介者模式(Mediator Pattern) 是一种行为型设计模式,其核心思想是通过引入一个 “中介者” 对象,封装多个对象之间的复杂交互逻辑,使原本相互耦合的对象不再直接通信,而是通过中介者间接交互。这一模式遵循 “迪米特法则”(最少知识原则),旨在降低对象间的耦合度,提高系统的可维护性和扩展性。

简单来说,中介者模式就像现实中的 “项目经理”—— 团队成员无需直接沟通协调任务,只需向项目经理汇报进度、提出需求,由项目经理统一分配资源、协调工作,避免了成员间的混乱交互。在软件系统中,当多个对象存在多对多依赖关系时,中介者模式能将复杂的网状依赖转化为清晰的星状结构(中介者为中心,其他对象为节点)。

二、中介者模式的核心结构

中介者模式包含以下 4 个关键角色,各角色职责明确、协同工作:

  1. 抽象中介者(Mediator):定义中介者与各个同事对象交互的接口,通常包含注册同事对象、转发同事请求的抽象方法。

  2. 具体中介者(ConcreteMediator):实现抽象中介者的接口,维护所有同事对象的引用,封装具体的交互逻辑。当收到某个同事的请求时,会根据业务规则协调其他相关同事做出响应。

  3. 抽象同事类(Colleague):定义同事对象的公共接口,包含一个指向中介者对象的引用(确保同事能通过中介者通信),以及发送请求、接收响应的抽象方法。

  4. 具体同事类(ConcreteColleague):实现抽象同事类的接口,当自身状态变化或需要交互时,不会直接通知其他同事,而是通过中介者传递信息;同时接收中介者转发的其他同事的请求并做出处理。

三、中介者模式的工作原理

中介者模式的交互流程可概括为 3 步:

  1. 注册阶段:所有具体同事对象在初始化时,将自身引用注册到具体中介者中,使中介者能管理所有同事。

  2. 请求传递:当某个同事需要与其他同事交互时,不会直接调用其他同事的方法,而是调用自身的 “发送请求” 方法,将请求传递给中介者。

  3. 中介协调:具体中介者收到请求后,根据预设的业务逻辑,判断需要通知哪些其他同事,并调用这些同事的 “接收响应” 方法,完成交互。

四、实际场景案例:电商订单支付流程

以电商平台的 “订单支付 - 库存扣减 - 物流创建” 流程为例,未使用中介者模式时,订单系统、库存系统、物流系统会直接相互调用,形成复杂耦合(订单支付后需调用库存扣减,库存扣减成功后需调用物流创建);使用中介者模式后,流程如下:

1. 角色定义

  • 抽象中介者(OrderMediator):定义注册系统、协调流程的接口。

  • 具体中介者(OrderProcessMediator):维护订单、库存、物流系统的引用,封装 “支付 - 扣库存 - 创物流” 的逻辑。

  • 抽象同事类(SystemColleague):包含中介者引用,定义发送请求、接收响应的方法。

  • 具体同事类:订单系统(OrderSystem)、库存系统(InventorySystem)、物流系统(LogisticsSystem)。

2. 交互流程

  1. 订单系统(OrderSystem)接收用户支付请求后,不直接调用库存系统,而是通过中介者发送 “支付成功” 请求。

  2. 具体中介者(OrderProcessMediator)收到请求后,先调用库存系统的 “扣减库存” 方法。

  3. 库存系统执行扣减后,通过中介者返回 “库存充足,扣减成功” 响应。

  4. 中介者继续调用物流系统的 “创建物流单” 方法,完成整个流程。

  5. 若库存不足,中介者会通知订单系统触发 “支付退款” 流程,无需订单系统直接判断库存状态。

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,请注意查收

五、中介者模式的优缺点

优点

  1. 降低耦合度:消除了同事对象间的直接依赖,将多对多耦合转化为中介者与同事的一对多耦合,便于系统维护。

  2. 集中控制交互:所有交互逻辑集中在中介者中,清晰可见,便于修改和扩展(如新增 “优惠券抵扣” 流程,只需修改中介者逻辑,无需改动同事类)。

  3. 简化对象职责:同事对象无需关注其他对象的交互细节,只需专注自身业务逻辑,符合 “单一职责原则”。

缺点

  1. 中介者膨胀风险:随着系统复杂度增加,中介者会封装越来越多的交互逻辑,可能导致中介者类过于庞大、难以维护(称为 “中介者反模式”)。

  2. 依赖集中:所有同事对象都依赖中介者,若中介者出现故障,整个系统的交互都会受影响,存在 “单点故障” 风险。

六、适用场景与使用建议

适用场景

  1. 多个对象存在复杂的多对多交互,导致对象间耦合严重,难以维护。

  2. 希望集中管理对象间的交互逻辑,便于统一修改和扩展。

  3. 系统中存在多个 “协调者” 角色,需避免协调逻辑分散在各个对象中。

使用建议

  1. 拆分复杂中介者:若中介者逻辑过于庞大,可将其拆分为多个细分中介者(如按业务模块拆分 “支付中介者”“物流中介者”),或结合其他模式(如策略模式)封装不同的交互策略。

  2. 避免过度使用:若对象间交互简单(仅一对一或少量依赖),无需引入中介者,否则会增加系统复杂度。

  3. 结合观察者模式:当同事对象状态变化需要通知多个其他同事时,可在中介者中整合观察者模式,简化通知逻辑。

七、与其他设计模式的区别

  1. 中介者模式 vs 观察者模式
  • 观察者模式是 “一对多” 的通知机制,焦点在 “状态变化通知”,观察者与被观察者无直接依赖,但交互逻辑分散在观察者中。
  • 中介者模式是 “多对多” 的交互协调,焦点在 “复杂交互管理”,通过中介者集中控制,同事对象完全依赖中介者
  1. 中介者模式 vs 外观模式
  • 外观模式是为子系统提供统一的入口,简化子系统的调用,不改变子系统内部的交互逻辑。
  • 中介者模式是改变子系统内部的交互方式,将分散的交互集中到中介者,降低子系统内部耦合。
posted @ 2025-12-11 00:20  圣祖帝皇  阅读(27)  评论(0)    收藏  举报