中介者模式
通过中介者对象协调多个对象之间的交互
问题
什么是中介者模式?如何在 JavaScript 中实现?
解答
中介者模式用一个中介对象来封装一系列对象之间的交互,使对象之间不直接引用,从而降低耦合度。
基础实现
// 中介者
class Mediator {
constructor() {
this.colleagues = {}
}
// 注册同事对象
register(name, colleague) {
this.colleagues[name] = colleague
colleague.mediator = this
}
// 转发消息
send(message, from, to) {
if (to) {
// 发送给指定对象
this.colleagues[to]?.receive(message, from)
} else {
// 广播给所有人
Object.keys(this.colleagues).forEach(name => {
if (name !== from) {
this.colleagues[name].receive(message, from)
}
})
}
}
}
// 同事类
class Colleague {
constructor(name) {
this.name = name
this.mediator = null
}
send(message, to) {
console.log(`${this.name} 发送: ${message}`)
this.mediator.send(message, this.name, to)
}
receive(message, from) {
console.log(`${this.name} 收到来自 ${from} 的消息: ${message}`)
}
}
// 使用
const mediator = new Mediator()
const alice = new Colleague('Alice')
const bob = new Colleague('Bob')
const charlie = new Colleague('Charlie')
mediator.register('Alice', alice)
mediator.register('Bob', bob)
mediator.register('Charlie', charlie)
alice.send('你好', 'Bob') // 私聊
bob.send('大家好') // 广播
聊天室示例
class ChatRoom {
constructor() {
this.users = new Map()
}
join(user) {
this.users.set(user.name, user)
user.chatRoom = this
this.broadcast(`${user.name} 加入了聊天室`, 'System')
}
leave(user) {
this.users.delete(user.name)
this.broadcast(`${user.name} 离开了聊天室`, 'System')
}
sendMessage(message, from, to) {
const target = this.users.get(to)
if (target) {
target.receive(message, from)
}
}
broadcast(message, from) {
this.users.forEach((user, name) => {
if (name !== from) {
user.receive(message, from)
}
})
}
}
class User {
constructor(name) {
this.name = name
this.chatRoom = null
}
send(message, to) {
if (to) {
this.chatRoom.sendMessage(message, this.name, to)
} else {
this.chatRoom.broadcast(message, this.name)
}
}
receive(message, from) {
console.log(`[${this.name}] ${from}: ${message}`)
}
}
// 使用
const room = new ChatRoom()
const user1 = new User('张三')
const user2 = new User('李四')
const user3 = new User('王五')
room.join(user1)
room.join(user2)
room.join(user3)
user1.send('大家好!') // 广播
user2.send('你好张三', '张三') // 私聊
事件中介者
class EventMediator {
constructor() {
this.events = {}
}
// 订阅事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(callback)
// 返回取消订阅函数
return () => this.off(event, callback)
}
// 取消订阅
off(event, callback) {
if (!this.events[event]) return
this.events[event] = this.events[event].filter(cb => cb !== callback)
}
// 发布事件
emit(event, data) {
if (!this.events[event]) return
this.events[event].forEach(callback => callback(data))
}
}
// 组件通过中介者通信
const mediator = new EventMediator()
// 组件 A
const componentA = {
init() {
mediator.on('dataUpdate', data => {
console.log('A 收到数据更新:', data)
})
},
updateData(data) {
mediator.emit('dataUpdate', data)
}
}
// 组件 B
const componentB = {
init() {
mediator.on('dataUpdate', data => {
console.log('B 收到数据更新:', data)
})
}
}
componentA.init()
componentB.init()
componentA.updateData({ value: 100 })
关键点
- 解耦对象:对象之间不直接通信,通过中介者转发
- 集中控制:交互逻辑集中在中介者中,便于维护
- 适用场景:聊天室、表单联动、组件通信、状态管理
- 与观察者区别:观察者是一对多广播,中介者是多对多协调
- 注意事项:中介者可能变得复杂,需要合理拆分
目录