19_中介者模式 Mediator Pattern
1. 基本信息
中文名称: 中介者模式
英文名称: Mediator Pattern
模式类型: 行为型设计模式
Rust 中常见实现方式: trait + 结构体 + Rc/Arc + RefCell/Mutex、channel、闭包
中介者模式的核心是:将对象之间的通信封装到中介者中,降低对象之间的直接耦合,让对象只依赖中介者而非彼此。
在 Rust 中,中介者模式通常通过 trait + 包装结构体 或 消息通道 实现,支持松耦合的对象通信和事件协调。
2. 模式核心思想
中介者模式的核心思想是:
通过一个中介者对象封装多个对象之间的交互,所有对象不直接通信,而通过中介者进行协调。
换句话说:
- 参与对象(Colleague)只依赖中介者接口
- 中介者管理对象交互逻辑
- 对象耦合度降低,系统可维护性和扩展性增强
3. 这个模式解决什么问题
在实际开发中,中介者模式主要解决以下问题:
多个对象之间存在复杂依赖和交互
直接通信导致耦合度高,系统难以维护
希望集中管理对象之间的协调逻辑
对象可能会动态增加或替换
典型场景:
- GUI 控件事件协调(按钮、文本框、列表等)
- 聊天系统:多个用户通过服务器中介发送消息
- 交通控制:各个设备通过中介协调状态
- 任务调度系统:多个任务通过调度器协调执行
- 游戏事件:玩家、NPC、环境通过中介管理事件
4. 不使用这个模式会怎样
如果不使用中介者模式,可能出现:
对象之间直接依赖,形成网状耦合
系统复杂度高,维护困难
修改一个对象可能影响其他多个对象
难以扩展或增加新的交互对象
5. 传统面向对象中的实现思路
在传统 OOP 中,中介者模式通常有两个角色:
Mediator(中介者接口):声明协调对象交互的方法
ConcreteMediator(具体中介者):实现中介者接口,管理各个 Colleague
Colleague(同事类):依赖中介者接口与其他对象通信
调用流程:
- Colleague 调用中介者方法
- 中介者根据逻辑协调其他 Colleague
- 避免 Colleague 直接互相调用
结构示意:
Mediator
└── notify(sender, event)
ConcreteMediator
└── 实现 notify,协调各 Colleague
Colleague
├── send(event)
└── receive(event)
6. Rust 中的实现思路
6.1 Rust 中通常怎么实现
在 Rust 中,中介者模式通常通过 trait + Rc/Arc + RefCell/Mutex 或 channel 实现:
#![allow(unused)]
fn main() {
// 中介者接口
trait Mediator {
fn notify(&self, sender: &str, event: &str);
}
// 具体中介者
use std::rc::Rc;
use std::cell::RefCell;
struct ConcreteMediator {
colleague_a: Rc<ColleagueA>,
colleague_b: Rc<ColleagueB>,
}
impl Mediator for ConcreteMediator {
fn notify(&self, sender: &str, event: &str) {
println!("中介者接收 {} 的事件: {}", sender, event);
if sender == "A" {
self.colleague_b.receive(event);
} else {
self.colleague_a.receive(event);
}
}
}
// Colleague
struct ColleagueA { mediator: Rc<dyn Mediator> }
struct ColleagueB { mediator: Rc<dyn Mediator> }
impl ColleagueA {
fn send(&self, event: &str) { self.mediator.notify("A", event); }
fn receive(&self, event: &str) { println!("A 收到事件: {}", event); }
}
impl ColleagueB {
fn send(&self, event: &str) { self.mediator.notify("B", event); }
fn receive(&self, event: &str) { println!("B 收到事件: {}", event); }
}
}
或者在多线程异步场景下,使用 channel:
#![allow(unused)]
fn main() {
let (tx, rx) = std::sync::mpsc::channel::<Event>();
// 各 Colleague 发送事件到 tx,中介者监听 rx 并协调
}
6.2 和传统 OOP 写法相比有什么不同
Rust 不依赖类继承体系,trait + Rc/Arc/RefCell/Mutex 替代中介者接口和对象引用。
静态类型保证对象安全,避免空引用或悬挂指针。
多线程场景可通过 channel 或 Arc/Mutex 安全通信。
动态分发可通过 Box<dyn Mediator> 或 Arc<dyn Mediator> 实现灵活中介。
6.3 Rust 中是否有更自然的替代写法
- 单线程简单场景可直接用
Rc<RefCell<>>管理对象,调用 trait 方法协调。 - 异步或跨线程场景可用 ch`annel 做事件总线,实现解耦。
- 对简单事件流,也可用闭包数组代替 trait 对象。
7. Rust 中涉及的语言特性
trait
impl
Rc/Arc + RefCell/Mutex
Box<dyn Trait>(动态分发可选)
所有权和借用
channel(异步事件)
闭包(可选,用于事件回调)
8. 性能与工程代价
- 静态分发中介者性能接近直接方法调用
Box<dyn Trait>或channel动态分发增加一次虚函数或消息开销- 多线程异步实现增加同步或锁开销
- 链条或事件订阅过多可能增加 CPU 消耗
- Rust 的所有权检查保证内存安全,无 GC 开销
9. 典型应用场景
1. GUI 控件事件协调(按钮、文本框、列表等)
2. 聊天系统消息中介(用户之间通过服务器通信)
3. 任务调度系统(调度器协调多个任务执行)
4. 交通控制或设备协调
5. 游戏事件系统(玩家、NPC、环境事件协调)
10. 和相似模式的区别
- 观察者模式:观察者模式通知所有依赖对象;中介者模式通过中心对象协调对象交互,通常单条链路。
- 责任链模式:责任链模式请求沿链传递,每个对象可处理或传递;中介者模式通过中心统一处理多个对象的交互。
- 代理模式:代理模式控制访问或增强对象;中介者模式负责协调对象之间的交互。
- 外观模式:外观模式提供统一接口简化调用;中介者模式关注对象间通信和协调机制。
11. 使用该模式的优点
降低对象之间的耦合度
所有对象通过中介者交互,逻辑集中管理
易于增加新的对象或改变交互逻辑
支持松耦合的事件驱动或异步通信
可结合 trait、Box、channel 实现线程安全
12. 使用该模式的代价
中介者对象可能变得复杂
动态分发或 channel 有性能开销
调试逻辑可能较复杂,事件链条难追踪
过度集中可能增加单点逻辑负担
13. 什么时候不应该使用
系统对象少,交互简单
对象间关系稳定且不需要动态协调
单线程简单调用可直接引用对象
过度集中逻辑增加维护成本
14. 一个简单例子思路
场景: GUI 控件事件协调
- 中介者对象
UiMediator - 控件:Button、TextBox、List
- Button 点击 → 通知 Mediator
- Mediator 协调 TextBox 和 List 行为
- 调用方直接操作 Mediator,无需知道控件内部逻辑
适合练习 Rust 特性:trait、Box<dyn Trait>、Rc/RefCell、Arc/Mutex、多线程 channel、闭包回调。
15. 总结一句话
中介者模式的本质是:通过中心对象管理多个对象之间的交互,实现松耦合、集中管理和灵活协调。在 Rust 中,trait + 包装结构体、Box/Arc/RefCell/Mutex 或 channel 是实现中介者模式的常用方法。