观察者模式算是前端最常用的设计模式了
直观的来讲,观察者模式就是让代码不需要实时的监听,而是当代码相关的事件被触发的时候,执行相应的事件
举个例子
就像去饭店点餐一样,我们点了一份米饭(注册了一个事件),那我们不需要一直站在那里等(系统不需要一直监听着这个事件),而是我们可以坐在位置上,刷手机、聊天,去等饭(cpu可以在此期间去做其他的事情),当饭做好了,服务员会叫我们去端饭,或者直接将饭端给我们(事件被触发了,就直接通知cpu,并去执行后续的操作)
场景
就像vue的响应式原理一样,系统不需要实时的去监听数据是否发生了变化,而是在数据变化的时候观察者模式可以直接捕获到,然后去通知相应的dom进行重新的render
vue的生命周期、vue的watch、各种dom的事件(click、scroll、resize)其实都是使用了观察者模式
代码
一般观察者模式里边,会有“观察者”,也会有“发布者”,发布者会收集需要被通知的“观察者”,并在数据发生变化的时候通知相应的观察者,观察者收到数据发生变化的通知之后,就会根据发生的变化再去做下一步的操作
当然,这个地方的“观察者”和“发布者”会令人想起发布订阅模式,但是发布订阅模式和观察者模式并不是一个模式,两者是有区别的
// 发布者
class Subject {
private state: number = 0
private observers: Observer[] = []
getState() {
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 ${this.state}`)
}
}
const sub = new Subject()
const observer1 = new Observer('A')
const observer2 = new Observer('A')
sub.attach(observer1)
sub.attach(observer2)
sub.setState(1)
发布订阅模式
发布订阅模式算是观察者模式的另一种实现形式,不属于传统的23种设计模式,但我们平时提到观察者模式和发布订阅模式也可以不必区分的那么细致
观察者模式和发布订阅模式之间最大的区别就是,发布订阅模式下可以自定义触发时机,可以直接对标vue中的EventBus,通过on()注册emit()触发