观察者模式实例
用生活场景理解观察者模式并实现
问题
用生活中的例子解释观察者模式,并用代码实现。
解答
生活场景:微信公众号
观察者模式就像订阅公众号:
- 公众号是被观察者(Subject)
- 订阅者是观察者(Observer)
- 公众号发文时,所有订阅者都会收到通知
代码实现
// 被观察者:公众号
class WeChatAccount {
constructor(name) {
this.name = name
this.subscribers = [] // 订阅者列表
}
// 添加订阅者
subscribe(observer) {
if (!this.subscribers.includes(observer)) {
this.subscribers.push(observer)
console.log(`${observer.name} 订阅了 ${this.name}`)
}
}
// 取消订阅
unsubscribe(observer) {
const index = this.subscribers.indexOf(observer)
if (index > -1) {
this.subscribers.splice(index, 1)
console.log(`${observer.name} 取消订阅 ${this.name}`)
}
}
// 发布文章,通知所有订阅者
publish(article) {
console.log(`\n${this.name} 发布了: ${article}`)
this.subscribers.forEach(observer => {
observer.update(this.name, article)
})
}
}
// 观察者:订阅者
class Subscriber {
constructor(name) {
this.name = name
}
// 收到通知时的处理
update(accountName, article) {
console.log(`${this.name} 收到 ${accountName} 的推送: ${article}`)
}
}
// 使用示例
const techAccount = new WeChatAccount('前端早读课')
const zhangsan = new Subscriber('张三')
const lisi = new Subscriber('李四')
const wangwu = new Subscriber('王五')
// 订阅
techAccount.subscribe(zhangsan)
techAccount.subscribe(lisi)
techAccount.subscribe(wangwu)
// 发布文章
techAccount.publish('JavaScript 闭包解析')
// 李四取消订阅
techAccount.unsubscribe(lisi)
// 再次发布
techAccount.publish('Promise 使用技巧')
输出结果:
张三 订阅了 前端早读课
李四 订阅了 前端早读课
王五 订阅了 前端早读课
前端早读课 发布了: JavaScript 闭包解析
张三 收到 前端早读课 的推送: JavaScript 闭包解析
李四 收到 前端早读课 的推送: JavaScript 闭包解析
王五 收到 前端早读课 的推送: JavaScript 闭包解析
李四 取消订阅 前端早读课
前端早读课 发布了: Promise 使用技巧
张三 收到 前端早读课 的推送: Promise 使用技巧
王五 收到 前端早读课 的推送: Promise 使用技巧
其他生活实例
| 场景 | 被观察者 | 观察者 |
|---|---|---|
| 红绿灯 | 交通灯 | 行人、车辆 |
| 拍卖会 | 拍卖师 | 竞拍者 |
| 股票 | 股价 | 股民 |
| 外卖 | 订单状态 | 顾客 |
关键点
- 一对多关系:一个被观察者对应多个观察者
- 松耦合:被观察者不需要知道观察者的具体实现
- 主动推送:状态变化时自动通知,观察者无需轮询
- DOM 事件就是观察者模式:
addEventListener添加观察者,事件触发时通知 - 与发布订阅的区别:观察者模式是直接通知,发布订阅有中间的事件中心
目录