观察者与发布订阅(面试版)
一、面试常考点
1. 两者核心区别
观察者是“直接依赖”;发布订阅是“通过事件中心解耦”。
2. 为什么容易混淆
两者都体现“一对多通知”,但依赖关系不同。
3. 面试追问点
事件中心如何防止内存泄漏、如何做一次订阅与解绑。
二、细节介绍
1. 观察者模式
Subject 持有 Observer 列表,状态变化时直接通知。
2. 发布订阅模式
Publisher 和 Subscriber 不直接耦合,由 EventBus 转发消息。
3. 工程侧注意
事件监听必须可解绑,否则容易造成重复触发和内存泄漏。
三、示例代码
class EventBus {
constructor() {
this.events = new Map()
}
on(eventName, handler) {
const arr = this.events.get(eventName) || []
arr.push(handler)
this.events.set(eventName, arr)
return () => this.off(eventName, handler)
}
off(eventName, handler) {
const arr = this.events.get(eventName) || []
this.events.set(
eventName,
arr.filter((fn) => fn !== handler)
)
}
emit(eventName, payload) {
const arr = this.events.get(eventName) || []
arr.forEach((fn) => fn(payload))
}
}
const bus = new EventBus()
const cancel = bus.on('order.created', (data) => {
console.log('send email:', data.id)
})
bus.emit('order.created', { id: 'A1001' })
cancel()
四、常用应用场景
1. 前端事件总线
跨组件通信(中小项目)。
2. 业务异步通知
下单后通知库存、物流、消息中心。
3. 系统监控
状态变化广播给日志、埋点、告警模块。
五、高频追问标准答法(Q/A)
1. Q: 观察者和发布订阅一句话区别
A: 观察者是主体直接通知观察者;发布订阅通过事件中心中转,解耦更强。
2. Q: 事件总线常见问题
A: 不解绑导致内存泄漏、事件名冲突、事件链难追踪。
3. Q: 如何避免事件系统失控
A: 事件命名分层、强制解绑、关键事件埋点、减少全局泛滥广播。