UML类图:
示例代码
// 主题
class Subject {
private state: number = 0
private observers: Observer[] = []
getState(): number {
return this.state
}
setState(newState: number) {
this.state = newState
this.notify() // 通知
}
// 添加观察者
attach(observer: Observer) {
this.observers.push(observer)
}
// 通知
private notify() {
this.observers.forEach(observer => {
observer.update(this.state)
})
}
}
// 观察者
class Observer {
name: string
constructor(name: string) {
this.name = name
}
update(state: number) {
console.log(`${this.name} updated, state is ${state}`)
}
}
const sub = new Subject()
const observer1 = new Observer('A')
sub.attach(observer1)
const observer2 = new Observer('B')
sub.attach(observer2)
sub.setState(1)
是否符合设计原则?
- Observer 和 Subject分离,解耦
- Observer可自由扩展
- Subject可自由扩展
观察者模式使用场景
- DOM事件
- Vue React 组件生命周期
- Vue watch
- Vue 组件更新过程
- 各种异步回调(setTimeOut/setInterval/Promise.then)
- MutationObserver
观察者模式VS发布订阅模式
发布订阅模式不属于传统的23种设计模式 是观察者模式的另一种实现
区别
- 观察者:Subject和Observer 直接绑定,中间无媒介
- 发布订阅:Publisher和Observer互不相识,中间有媒介
场景
- 1.自定义事件
mitt
event-emitter
- 2.postMessage通讯
iframe通讯
main发送
main:接收
child接收
child发送:
注意事项:自定义事件要及时Off
- 组件销毁之前off,避免内存泄露
- off时要传入之前的函数(而非匿名函数)