Skip to content

中介者模式(Mediator Pattern)笔记

定义

中介者模式是一种行为设计模式,它定义一个对象来封装一组对象之间的交互,使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

英文原文定义

The Mediator Pattern defines an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

核心概念

中介者模式通过引入中介者对象来管理对象间复杂的交互关系,将网状结构变为星型结构,降低了对象间的直接耦合。

主要角色

  1. Mediator(抽象中介者):定义同事对象到中介者对象的接口
  2. ConcreteMediator(具体中介者):协调各同事对象实现协作行为
  3. Colleague(抽象同事类):定义各同事类公有方法,维持对中介者的引用
  4. ConcreteColleague(具体同事类):实现自身业务逻辑,通过中介者与其他同事通信

优缺点

优点

  • 降低耦合度:将对象间多对多关系转化为一对多关系
  • 简化对象协议:用中介者和同事间的一对多交互替代多对多交互
  • 集中控制:将交互复杂性集中到中介者中
  • 复用性提高:各同事类可被独立复用
  • 开闭原则:新增中介者无需修改现有代码

缺点

  • 中介者可能复杂:随着交互逻辑增加,中介者可能变得过于复杂
  • 性能瓶颈:中介者可能成为系统性能瓶颈
  • 过度集中:过度使用可能导致中介者承担过多责任
  • 调试困难:交互逻辑集中在中介者中可能使调试复杂化

解决的问题

中介者模式主要解决以下经典问题:

  1. 复杂对象引用:对象间存在大量复杂关联关系时
  2. 交互逻辑分散:对象间交互行为分散在各个对象中难以维护时
  3. 复用困难:由于对象间强耦合导致难以独立复用时
  4. 分布式通信:需要集中管理对象间通信时
  5. UI组件协调:GUI中各组件需要复杂协调时

实现注意事项

  1. 中介者职责边界

    • 明确中介者只负责协调,不承担业务逻辑
    • 避免中介者成为"上帝对象"
  2. 同事类设计

    • 同事类应保持对中介者的弱引用
    • 同事类间不应有直接依赖
  3. 接口设计

    • 定义清晰的中介者接口
    • 避免中介者接口过于臃肿
  4. 性能考量

    • 对于高频交互系统,考虑中介者性能影响
    • 可能需要引入缓存或异步机制
  5. 错误处理

    • 设计良好的错误传播机制
    • 避免中介者成为单点故障

实现变体

  1. 事件驱动中介者

    • 使用观察者模式实现松散耦合
    • 同事通过事件与中介者通信
  2. 命令总线模式

    • 将请求封装为命令对象
    • 中介者作为命令总线分发命令
  3. 微内核架构

    • 中介者作为系统核心
    • 各功能作为插件与核心通信
  4. 面向消息中介

    • 基于消息队列实现中介
    • 支持异步和分布式通信

与其他模式的关系

相似模式区分

  1. 观察者模式

    • 中介者:集中处理同事对象间双向交互
    • 观察者:处理对象间单向通知关系
  2. 门面模式

    • 中介者:协调平等对象间的交互
    • 门面:为子系统提供统一接口
  3. 代理模式

    • 中介者:协调多个对象间关系
    • 代理:控制对一个对象的访问

常见搭配组合

  1. 中介者 + 观察者:实现事件驱动架构
  2. 中介者 + 命令:封装请求为命令对象
  3. 中介者 + 组合:处理复杂组件结构
  4. 中介者 + 享元:共享无状态的同事对象

典型应用场景

  • 聊天应用程序(聊天室作为中介者)
  • 航空交通管制系统
  • GUI组件交互(如表单验证)
  • 分布式系统协调
  • 工作流引擎
  • 多玩家游戏系统
  • 企业服务总线(ESB)

代码示例(聊天室实现)

java
// 抽象中介者
interface ChatMediator {
    void sendMessage(String msg, User user);
    void addUser(User user);
}

// 具体中介者:聊天室
class ChatRoom implements ChatMediator {
    private List<User> users = new ArrayList<>();
    
    @Override
    public void sendMessage(String msg, User user) {
        for (User u : users) {
            // 不发送给消息发起者
            if (u != user) {
                u.receive(msg);
            }
        }
    }
    
    @Override
    public void addUser(User user) {
        this.users.add(user);
    }
}

// 抽象同事类
abstract class User {
    protected ChatMediator mediator;
    protected String name;
    
    public User(ChatMediator med, String name) {
        this.mediator = med;
        this.name = name;
    }
    
    public abstract void send(String msg);
    public abstract void receive(String msg);
}

// 具体同事类
class ChatUser extends User {
    public ChatUser(ChatMediator med, String name) {
        super(med, name);
    }
    
    @Override
    public void send(String msg) {
        System.out.println(this.name + " 发送: " + msg);
        mediator.sendMessage(msg, this);
    }
    
    @Override
    public void receive(String msg) {
        System.out.println(this.name + " 收到: " + msg);
    }
}

// 客户端代码
public class ChatClient {
    public static void main(String[] args) {
        ChatMediator mediator = new ChatRoom();
        
        User john = new ChatUser(mediator, "John");
        User jane = new ChatUser(mediator, "Jane");
        User doe = new ChatUser(mediator, "Doe");
        
        mediator.addUser(john);
        mediator.addUser(jane);
        mediator.addUser(doe);
        
        john.send("Hi everyone!");
        jane.send("Hello John!");
    }
}