中介者模式

用中介者对象协调多个对象间的通信

问题

什么是中介者模式?如何在 JavaScript 中实现?

解答

中介者模式通过引入一个中介者对象,让多个对象不再直接相互引用,而是通过中介者进行通信。这样可以降低对象间的耦合度。

场景示例:聊天室

// 中介者:聊天室
class ChatRoom {
  constructor() {
    this.users = {};
  }

  // 注册用户
  register(user) {
    this.users[user.name] = user;
    user.chatRoom = this;
  }

  // 发送消息给指定用户
  send(message, from, to) {
    if (to) {
      // 私聊
      to.receive(message, from);
    } else {
      // 群发
      Object.values(this.users).forEach(user => {
        if (user !== from) {
          user.receive(message, from);
        }
      });
    }
  }
}

// 同事类:用户
class User {
  constructor(name) {
    this.name = name;
    this.chatRoom = null;
  }

  // 发送消息
  send(message, to) {
    this.chatRoom.send(message, this, to);
  }

  // 接收消息
  receive(message, from) {
    console.log(`${from.name} -> ${this.name}: ${message}`);
  }
}

// 使用
const chatRoom = new ChatRoom();

const alice = new User('Alice');
const bob = new User('Bob');
const charlie = new User('Charlie');

chatRoom.register(alice);
chatRoom.register(bob);
chatRoom.register(charlie);

alice.send('大家好!');          // 群发
// Bob 收到: Alice -> Bob: 大家好!
// Charlie 收到: Alice -> Charlie: 大家好!

bob.send('你好 Alice', alice);   // 私聊
// Alice -> Alice: 你好 Alice

事件中介者

// 通用事件中介者
class Mediator {
  constructor() {
    this.channels = {};
  }

  // 订阅
  subscribe(channel, callback) {
    if (!this.channels[channel]) {
      this.channels[channel] = [];
    }
    this.channels[channel].push(callback);
  }

  // 发布
  publish(channel, data) {
    if (!this.channels[channel]) return;
    this.channels[channel].forEach(callback => callback(data));
  }
}

// 使用:组件间通信
const mediator = new Mediator();

// 组件 A 订阅
mediator.subscribe('priceUpdate', price => {
  console.log(`组件A 收到价格更新: ${price}`);
});

// 组件 B 订阅
mediator.subscribe('priceUpdate', price => {
  console.log(`组件B 收到价格更新: ${price}`);
});

// 组件 C 发布
mediator.publish('priceUpdate', 99.9);
// 组件A 收到价格更新: 99.9
// 组件B 收到价格更新: 99.9

对比:无中介者 vs 有中介者

// ❌ 无中介者:对象直接引用,耦合度高
class ComponentA {
  constructor(b, c) {
    this.b = b;
    this.c = c;
  }
  notify() {
    this.b.update();
    this.c.update();
  }
}

// ✅ 有中介者:通过中介者通信,解耦
class ComponentA {
  constructor(mediator) {
    this.mediator = mediator;
  }
  notify() {
    this.mediator.publish('update');
  }
}

关键点

  • 解耦:对象间不直接通信,通过中介者转发
  • 集中控制:交互逻辑集中在中介者中,便于维护
  • 适用场景:聊天室、表单联动、组件通信
  • 缺点:中介者可能变得复杂,成为”上帝对象”
  • 与观察者模式区别:中介者是双向通信,观察者是单向广播