三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Java 23 种设计模式:从踩坑到精通 | 番外:中介者模式 —— 物流服务协调实战

Java 23 种设计模式:从踩坑到精通 | 番外:中介者模式 —— 物流服务协调实战

Java 23 种设计模式:从踩坑到精通 | 番外:中介者模式 —— 物流服务协调实战

摘要:中介者模式用一个中介对象来封装一系列对象的交互,使各对象不需要显式地相互引用,从而使其耦合松散,将网状的多对多依赖关系转变为以中介者为中心的星型结构。本文结合智能物流调度中心的场景,完整展示如何用中介者协调订单、库存、配送三大服务的交互,并与外观模式深度对比,帮你掌握“化网为星”的设计精髓。

🗺️本文阅读地图(3 分钟速览)

  • 为什么订单、库存、配送服务不能直接互相调用?
  • 中介者核心角色:抽象中介者、具体中介者、抽象同事、具体同事
  • 手写物流调度中心:订单创建 → 库存扣减 → 配送发货,全程由中介者协调
  • 中介者 vs 外观:双向协调 vs 单向简化
  • 面试必问:“中介者模式和外观模式有什么区别?DispatcherServlet用了哪个?”

📖《Java 23 种设计模式:从踩坑到精通》
开篇:系列介绍与目录 | 正篇:Mediator 中介者模式 —— 对象关系太乱?请一位“中间人” |当前:番外 · 中介者模式 × 物流服务协调
🔗 返回系列总目录


1. 物流服务交互的痛点

在智能物流系统中,订单服务、库存服务、配送服务之间存在紧密的协作关系:订单创建后需要通知库存扣减,库存确认后需要通知配送发货,配送完成后需要通知订单更新状态。如果让这三个服务直接互相调用:

// 订单服务直接依赖库存服务和配送服务classOrderService{privateInventoryServiceinventoryService;privateDeliveryServicedeliveryService;voidcreateOrder(){inventoryService.deductStock();// 直接调用库存deliveryService.arrangeDelivery();// 直接调用配送}}

这种写法会让服务之间形成网状依赖——每新增一个服务(如支付服务、通知服务),所有相关服务都要修改。更糟糕的是,服务之间的调用顺序和交互规则散落在各服务内部,难以统一管理和动态调整。

中介者模式的解决思路:引入一个调度中心(中介者),让所有服务只与调度中心通信,不再直接互相调用。订单创建后通知调度中心,调度中心决定接下来调用库存服务,库存确认后再由调度中心调用配送服务——所有交互逻辑集中在调度中心内,各服务只需关注自己的业务。

1.1 你的场景该不该用中介者?

判断标准是 → 用中介者否 → 用其他方式
多个对象之间形成复杂的网状交互,耦合严重
交互逻辑频繁变化,需要集中管理和动态调整
希望各组件独立开发、独立测试
只有简单的一对一调用关系,无网状依赖直接调用即可

2. 中介者模式 UML(物流调度中心场景)


3. 完整源码实现

3.1 抽象中介者接口 (Mediator)

/** * 抽象中介者:定义同事类通知中介者的统一接口 */publicinterfaceMediator{voidnotify(Colleaguesender,Stringevent);}

💬白话:中介者只有一个核心方法——接收来自某个同事的消息,然后决定下一步通知谁。

3.2 抽象同事类 (Colleague)

/** * 抽象同事类:所有具体同事的基类 */publicabstractclassColleague{protectedMediatormediator;protectedStringname;publicColleague(Mediatormediator,Stringname){this.mediator=mediator;this.name=name;}publicabstractvoidsend(Stringevent);publicabstractvoidreceive(Stringevent);}

💬白话:每个同事都持有中介者的引用,发消息走中介者,收消息也从中介者来。同事之间互不相识。

3.3 具体中介者:物流调度中心 (ConcreteMediator)

/** * 具体中介者:物流调度中心,协调各服务之间的交互 */publicclassConcreteMediatorimplementsMediator{privateConcreteColleagueAorderService;privateConcreteColleagueBinventoryService;privateConcreteColleagueCdeliveryService;@Overridepublicvoidnotify(Colleaguesender,Stringevent){System.out.println("\n📡 [调度中心] 收到来自 ["+sender.name+"] 的消息:"+event);if(sender==orderService){handleOrderEvent(event);}elseif(sender==inventoryService){handleInventoryEvent(event);}elseif(sender==deliveryService){handleDeliveryEvent(event);}}privatevoidhandleOrderEvent(Stringevent){if(event.contains("已创建")){System.out.println(" → 调度中心:通知库存服务扣减库存");inventoryService.receive("订单已创建,请扣减库存");}}privatevoidhandleInventoryEvent(Stringevent){if(event.contains("库存充足")){System.out.println(" → 调度中心:通知配送服务安排发货");deliveryService.receive("库存已确认,请安排配送");}elseif(event.contains("库存不足")){System.out.println(" → 调度中心:通知订单服务取消订单");orderService.receive("库存不足,订单已取消");}}privatevoidhandleDeliveryEvent(Stringevent){if(event.contains("已发货")){System.out.println(" → 调度中心:通知订单服务更新物流状态");orderService.receive("商品已发货,物流单号:SF123456789");}}publicvoidsetOrderService(ConcreteColleagueAorderService){this.orderService=orderService;}publicvoidsetInventoryService(ConcreteColleagueBinventoryService){this.inventoryService=inventoryService;}publicvoidsetDeliveryService(ConcreteColleagueCdeliveryService){this.deliveryService=deliveryService;}}

💬白话:调度中心是“大脑”——它知道所有服务,所有交互规则都写在这里。订单创建后该做什么、库存确认后该做什么,全部集中管控。新增一个服务只需在中介者中增加对应的处理方法。

3.4 具体同事类:订单/库存/配送服务

/** * 具体同事类A:订单服务 */publicclassConcreteColleagueAextendsColleague{publicConcreteColleagueA(Mediatormediator,Stringname){super(mediator,name);}@Overridepublicvoidsend(Stringevent){System.out.println("📦 ["+name+"] 发送消息:"+event);mediator.notify(this,event);}@Overridepublicvoidreceive(Stringevent){System.out.println(" 📥 ["+name+"] 收到消息:"+event);}}/** * 具体同事类B:库存服务 */publicclassConcreteColleagueBextendsColleague{publicConcreteColleagueB(Mediatormediator,Stringname){super(mediator,name);}@Overridepublicvoidsend(Stringevent){System.out.println("📦 ["+name+"] 发送消息:"+event);mediator.notify(this,event);}@Overridepublicvoidreceive(Stringevent){System.out.println(" 📥 ["+name+"] 收到消息:"+event);if(event.contains("扣减库存")){booleanhasStock=true;// 模拟库存充足if(hasStock){send("库存充足,扣减完成");}else{send("库存不足,无法扣减");}}}}/** * 具体同事类C:配送服务 */publicclassConcreteColleagueCextendsColleague{publicConcreteColleagueC(Mediatormediator,Stringname){super(mediator,name);}@Overridepublicvoidsend(Stringevent){System.out.println("📦 ["+name+"] 发送消息:"+event);mediator.notify(this,event);}@Overridepublicvoidreceive(Stringevent){System.out.println(" 📥 ["+name+"] 收到消息:"+event);if(event.contains("安排配送")){send("已发货,物流单号:SF123456789");}}}

💬白话:每个服务只做两件事——send发消息给中介者,receive收消息并执行自己的业务逻辑。它们完全不知道其他服务的存在。

3.5 客户端测试

publicclassClient{publicstaticvoidmain(String[]args){ConcreteMediatordispatcher=newConcreteMediator();ConcreteColleagueAorderService=newConcreteColleagueA(dispatcher,"订单服务");ConcreteColleagueBinventoryService=newConcreteColleagueB(dispatcher,"库存服务");ConcreteColleagueCdeliveryService=newConcreteColleagueC(dispatcher,"配送服务");dispatcher.setOrderService(orderService);dispatcher.setInventoryService(inventoryService);dispatcher.setDeliveryService(deliveryService);System.out.println("=== 场景:用户下单,触发完整物流流程 ===\n");orderService.send("订单已创建,订单号:20240723001");System.out.println("\n=== 流程结束 ===");}}

4. 运行结果

=== 场景:用户下单,触发完整物流流程 === 📦 [订单服务] 发送消息:订单已创建,订单号:20240723001 📡 [调度中心] 收到来自 [订单服务] 的消息:订单已创建,订单号:20240723001 → 调度中心:通知库存服务扣减库存 📥 [库存服务] 收到消息:订单已创建,请扣减库存 📦 [库存服务] 发送消息:库存充足,扣减完成 📡 [调度中心] 收到来自 [库存服务] 的消息:库存充足,扣减完成 → 调度中心:通知配送服务安排发货 📥 [配送服务] 收到消息:库存已确认,请安排配送 📦 [配送服务] 发送消息:已发货,物流单号:SF123456789 📡 [调度中心] 收到来自 [配送服务] 的消息:已发货,物流单号:SF123456789 → 调度中心:通知订单服务更新物流状态 📥 [订单服务] 收到消息:商品已发货,物流单号:SF123456789 === 流程结束 ===

5. 核心角色回顾

角色职责对应代码
Mediator定义同事与中介者的通信接口Mediator
ConcreteMediator协调各同事的交互,集中管控规则ConcreteMediator
Colleague持有中介者引用,通过中介者通信Colleague
ConcreteColleague实现自身业务,发消息给中介者ConcreteColleagueA/B/C

6. 中介者模式 vs 外观模式

对比项中介者模式外观模式
意图协调多个对象之间的双向交互为子系统提供单向统一入口
通信方向同事 ↔ 中介者 ↔ 同事(双向)客户端 → 外观 → 子系统(单向)
子系统感知同事类知道中介者的存在子系统不知道外观的存在
典型应用物流调度中心、聊天室、DispatcherServletSLF4J、JdbcTemplate、微服务网关

💡一句话记忆:中介者是“中控台”——双向协调,每个服务都知道中介者;外观是“一键启动”——单向简化,子系统不知道外观的存在。

7. 中介者模式的优缺点

优点缺点
同事类之间零依赖,从网状变星型中介者可能膨胀为“上帝类”
交互逻辑集中管控,修改方便所有通信经过中介者,可能成为性能瓶颈
各组件可独立开发、独立测试设计复杂度增加

8. 六大设计原则体现

原则体现
单一职责同事负责自身业务,中介者负责协调
开闭原则新增同事类通常无需修改中介者(新增交互规则时需修改)
里氏替换所有同事可替换抽象Colleague
依赖倒置同事依赖抽象Mediator接口
接口隔离Mediator只有notify()一个方法
迪米特法则同事只与中介者通信,不知其他同事存在

附 中介者模式 UML源码(物流调度中心场景)

@startuml title Java 23 种设计模式:从踩坑到精通 footer 折哥 | 智能物流与Java实战 ' 1. 全局样式配置 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 skinparam interface { BackgroundColor #E8F5E9 BorderColor #2E7D32 } ' 2. 抽象中介者 interface Mediator { + notify(sender, event) } note right of Mediator <b>抽象中介者</b> -- 定义同事类通知中介者的统一接口 封装对象间的交互逻辑 end note ' 3. 具体中介者 class ConcreteMediator implements Mediator { - colleagueA : ConcreteColleagueA - colleagueB : ConcreteColleagueB + notify(sender, event) + setColleagueA(Colleague) + setColleagueB(Colleague) } note right of ConcreteMediator <b>具体中介者</b> -- 协调各同事类之间的交互 知道所有同事类,但同事类不知道彼此 end note ' 4. 抽象同事类 abstract class Colleague { - mediator : Mediator + send(event) + receive(event) } note right of Colleague <b>抽象同事类</b> -- 持有中介者引用 通过中介者与其他同事通信 不直接依赖其他同事类 end note ' 5. 具体同事类A class ConcreteColleagueA extends Colleague { + send(event) + receive(event) } note right of ConcreteColleagueA <b>具体同事类A</b> -- 例如:订单服务 只与中介者通信 end note ' 6. 具体同事类B class ConcreteColleagueB extends Colleague { + send(event) + receive(event) } note right of ConcreteColleagueB <b>具体同事类B</b> -- 例如:库存服务 只与中介者通信 end note ' 7. 关系连线 Colleague o-down-> Mediator : 依赖 ConcreteMediator .up.> Mediator : 实现 ConcreteColleagueA -up-|> Colleague : 继承 ConcreteColleagueB -up-|> Colleague : 继承 ConcreteMediator --> ConcreteColleagueA : 协调 ConcreteMediator --> ConcreteColleagueB : 协调 @enduml

🧭 《Java 23 种设计模式:从踩坑到精通》快速导航

  • 开篇:系列介绍与目录
  • 正篇:Mediator 中介者模式 —— 对象关系太乱?请一位“中间人”
  • 当前:番外 · 中介者模式 × 物流服务协调(你在这里)
  • 创建型模式汇总
  • 结构型模式汇总
  • 行为型模式汇总

🔔 关注《Java 23 种设计模式:从踩坑到精通》,用 25 篇文章彻底吃透设计模式。
📦福利预告:全系列代码及 UML 源码将在完结时统一打包开放,点击「关注」「收藏」第一时间获取。

📌 除了设计模式,我也在深挖智能物流实战(WMS、托盘调度、机器学习落地)。欢迎点击头像,看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通,思路可鉴。

← 返回列表