之前一直都认为观察者模式和发布订阅模式是一回事,包括网上的很多文章也是这么写的,但有一次面试中被问到两者的区别,直接懵了答不出来,经过最近的一些学习,慢慢理解了两者的不同。
在我看来,两者最主要的区别在于是否有中间的调度中心。
- 观察者模式把订阅者维护在发布者这里,需要发布消息时直接发消息给订阅者。在观察者模式中,发布者本身是知道订阅者存在的。
- 而发布/订阅模式中,发布者并不维护订阅者,也不知道订阅者的存在,所以也不会直接通知订阅者,而是通知调度中心,由调度中心通知订阅者。
由以上的描述可以看出,发布订阅模式是松散耦合的,而观察者模式强耦合。
观察者模式的场景:Vue的依赖追踪,原生事件。
发布订阅模式的场景: React的合成事件,vue组件间通信的EventBus。
观察者模式的一个例子:
class Observer { constructor (fn) { this.update = fn } } class Subject { constructor () { this.observers = [] } addObserver (observer) { this.observers.push(observer) } removeObserver (observer) { const delIndex = this.observers.indexOf(observer) this.observers.splice(delIndex, 1) } notify () { this.observers.forEach(observer => { observer.update() }) } } var subject = new Subject() var ob1 = new Observer(function () { console.log('ob1 callback run') }) subject.addObserver(ob1) var ob2 = new Observer(function () { console.log('ob2 callback run') }) subject.addObserver(ob2) subject.notify()
发布/订阅模式:
class EventBus { constructor () { this.events = Object.create(null) } on (event, fn) { this.events.event = this.events.event || [] this.events.event.push(fn) } off (event, fn) { const index = (this.events.event || []).indexOf(fn) if (index < -1) { return } else { this.events.event.splice(index, 1) } } fire (event) { this.events.event.forEach(fn => fn()) } } var bus = new EventBus() bus.on('onclick', function () { console.log('click1 fire') }) bus.on('onclick', fn=function () { console.log('click2 fire') }) bus.fire('onclick')
作者:勤奋的大鱼
链接:https://www.jianshu.com/p/a75b7917b850