20. 中介者模式(Mediator)

问题:多个对象之间直接互相引用,关系网状,改一个牵动一片。

核心:引入中介者,所有对象只和中介者通信。

class ChatRoom {
  #users: Map<string, User> = new Map();
  register(user: User): void { this.#users.set(user.name, user); }
  send(from: string, to: string, message: string): void {
    const target = this.#users.get(to);
    if (target) target.receive(from, message);
  }
}

class User {
  #room: ChatRoom;
  constructor(public readonly name: string, room: ChatRoom) {
    this.#room = room;
    room.register(this);
  }
  send(to: string, msg: string): void { this.#room.send(this.name, to, msg); }
  receive(from: string, msg: string): void { console.log(`${this.name} 收到 ${from} 的消息: ${msg}`); }
}

const room = new ChatRoom();
const alice = new User('Alice', room);
const bob = new User('Bob', room);

alice.send('Bob', '你好!');
// Bob 收到 Alice 的消息: 你好!
package mediator

import "fmt"

type ChatRoom struct {
  users map[string]*User
}

func NewChatRoom() *ChatRoom {
  return &ChatRoom{users: make(map[string]*User)}
}

func (r *ChatRoom) Register(user *User) {
  r.users[user.Name] = user
}

func (r *ChatRoom) Send(from, to, message string) {
  if target, ok := r.users[to]; ok {
    target.Receive(from, message)
  }
}

type User struct {
  Name string
  room *ChatRoom
}

func NewUser(name string, room *ChatRoom) *User {
  u := &User{Name: name, room: room}
  room.Register(u)
  return u
}

func (u *User) Send(to, msg string) {
  u.room.Send(u.Name, to, msg)
}

func (u *User) Receive(from, msg string) {
  fmt.Printf("%s 收到 %s 的消息: %s\n", u.Name, from, msg)
}

实战场景

  • 聊天室:用户之间不直接引用,消息统一交给房间对象转发、过滤和记录。
  • 表单联动:字段之间不互相调用,由表单控制器统一处理值变化、校验和显隐规则。
  • UI 组件协作:弹窗、表格、筛选器、分页器、工具栏通过页面级 mediator 协调状态。
  • 航班调度:飞机之间不直接沟通,由塔台统一协调起降、跑道、等待队列。
  • 工作流引擎:节点之间不直接调用,流程引擎决定下一步走向、条件分支和状态持久化。
  • 事件编排:订单支付成功后,需要通知库存、物流、发票、积分,中介者负责协调顺序和异常。
  • 游戏房间:玩家、怪物、道具、地图事件统一通过房间或场景管理器交互。
  • 微前端通信:子应用之间不直接依赖,由宿主或事件中心负责消息路由。
  • 协作编辑:光标、选区、文档内容、评论、在线用户通过协作控制器统一同步。
  • 设备联动:智能家居里的传感器、灯、空调、窗帘通过中心规则引擎协调,而不是彼此直接调用。