中介者模式
通过中间人协调多个对象之间的通信
问题
中介者模式是什么?如何实现?用”找媒人介绍对象”来理解。
解答
中介者模式让多个对象不直接相互引用,而是通过一个中介者来协调通信。就像相亲时,男女双方不直接联系,而是通过媒人传话。
基础实现
// 中介者(媒人)
class Matchmaker {
constructor() {
this.participants = {}
}
// 注册参与者
register(person) {
this.participants[person.name] = person
person.matchmaker = this
}
// 转发消息
send(message, from, to) {
const target = this.participants[to]
if (target) {
target.receive(message, from)
}
}
// 广播消息给所有人
broadcast(message, from) {
Object.values(this.participants).forEach(person => {
if (person.name !== from) {
person.receive(message, from)
}
})
}
}
// 参与者
class Person {
constructor(name) {
this.name = name
this.matchmaker = null
}
// 发送消息(通过媒人)
send(message, to) {
console.log(`${this.name} 说: ${message}`)
this.matchmaker.send(message, this.name, to)
}
// 接收消息
receive(message, from) {
console.log(`${this.name} 收到来自 ${from} 的消息: ${message}`)
}
}
// 使用
const matchmaker = new Matchmaker()
const zhangSan = new Person('张三')
const liSi = new Person('李四')
const wangWu = new Person('王五')
matchmaker.register(zhangSan)
matchmaker.register(liSi)
matchmaker.register(wangWu)
zhangSan.send('你好,想认识一下', '李四')
liSi.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')
}
sendTo(message, from, to) {
const user = this.users.get(to)
if (user) {
user.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
}
say(message) {
this.chatRoom.broadcast(message, this.name)
}
sayTo(message, to) {
this.chatRoom.sendTo(message, this.name, to)
}
receive(message, from) {
console.log(`[${this.name}] ${from}: ${message}`)
}
}
// 使用
const room = new ChatRoom()
const alice = new User('Alice')
const bob = new User('Bob')
const charlie = new User('Charlie')
room.join(alice)
room.join(bob)
room.join(charlie)
alice.say('大家好!')
bob.sayTo('Alice 你好', 'Alice')
表单验证中介者
// 表单中介者:协调多个输入框的验证
class FormMediator {
constructor() {
this.fields = {}
this.submitBtn = null
}
registerField(field) {
this.fields[field.name] = field
field.mediator = this
}
registerSubmitBtn(btn) {
this.submitBtn = btn
}
// 某个字段变化时,检查整体表单状态
fieldChanged(fieldName) {
const allValid = Object.values(this.fields).every(f => f.isValid)
if (this.submitBtn) {
this.submitBtn.disabled = !allValid
}
// 可以添加字段间的联动逻辑
// 比如:密码确认框依赖密码框
if (fieldName === 'password' && this.fields['confirmPassword']) {
this.fields['confirmPassword'].validate()
}
}
}
class FormField {
constructor(name, validator) {
this.name = name
this.validator = validator
this.value = ''
this.isValid = false
this.mediator = null
}
setValue(value) {
this.value = value
this.validate()
}
validate() {
this.isValid = this.validator(this.value, this.mediator?.fields)
this.mediator?.fieldChanged(this.name)
return this.isValid
}
}
// 使用
const form = new FormMediator()
const username = new FormField('username', v => v.length >= 3)
const password = new FormField('password', v => v.length >= 6)
const confirmPassword = new FormField('confirmPassword', (v, fields) => {
return v === fields?.password?.value
})
form.registerField(username)
form.registerField(password)
form.registerField(confirmPassword)
username.setValue('tom')
password.setValue('123456')
confirmPassword.setValue('123456')
关键点
- 解耦对象:对象之间不直接通信,通过中介者转发,降低耦合度
- 集中控制:交互逻辑集中在中介者中,便于维护和修改
- 适用场景:聊天室、表单联动、GUI 组件交互、飞机塔台调度
- 缺点:中介者可能变得复杂,成为”上帝对象”
- 与观察者模式区别:观察者是一对多广播,中介者是多对多协调
目录