Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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/Mutexchannel 实现:

#![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 是实现中介者模式的常用方法。