观察者模式 vs 发布订阅者模式
2021-05-12 本文已影响0人
Marshall3572
观察者模式(Observer pattern)和发布订阅模式(Publish–subscribe pattern)到底有什么不同?
观察者模式
所谓观察者模式,其实就是为了实现松耦合(loosely coupled)。
用《Head First设计模式》里的气象站为例子,每当气象测量数据有更新,changed()方法就会被调用,于是我们可以在changed()方法里面,更新气象仪器上的数据,比如温度、气压等等。
怎么解决呢?使用观察者模式,面向接口编程,实现松耦合。
观察者模式里面,changed()方法所在的实例对象,就是被观察者(Subject,或者叫Observable),它只需维护一套观察者(Observer)的集合,这些Observer实现相同的接口,Subject只需要知道,通知Observer时,需要调用哪个统一方法就好了:
但是这样写有个问题,就是如果以后我们想在changed()方法被调用时,更新更多的信息,比如说湿度,那就要去修改changed()方法的代码,这就是紧耦合的坏处。
主题对象Subject中有 添加观察者(addObserver)、删除观察者(removeObserver)、通知观察者更新(notify)几种方法。
class Subject {
constructor() {
this.observers = []
}
addObserver(observer) {
this.observers.push(observer)
}
removeObserver(observer) {
this.observers = this.observers.filter(o => o != observer)
}
notify() {
this.observers.forEach(observer => observer.update())
}
}
class Observer {
constructor(name) {
this.name = name
}
update() {
console.log(this.name + " updated")
}
subscribeTo(subject) {
subject.addObserver(this)
}
unsubscribe(subject) {
subject.removeObserver(this)
}
}
let subject1 = new Subject
let o1 = new Observer('a')
let o2 = new Observer('b')
// 订阅
o1.subscribe(subject1)
o2.subscribe(subject1)
// 取消订阅
// o1.unsubscribe(subject1)
// o2.unsubscribe(subject1)
subject1.notify()
发布订阅者模式
在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。
互不相识?那他们之间如何交流?
答案是,通过第三者,也就是在消息队列里面,我们常说的经纪人Broker。
当Broker收到发布者发过来消息,并且topic是AAA时,就会把消息推送给订阅了topic是AAA的订阅者。当然也有可能是订阅者自己过来拉取,看具体实现。发布订阅模式里,发布者和订阅者,不是松耦合,而是完全解耦的。
const EventManager = (function(){
let eventList = {}
function on(event, handler) {
if(!eventList[event]) {
eventList[event] = [handler]
}else {
eventList[event].push(handler)
}
}
function fire(event, data) {
if(eventList[event]) {
eventList[event].forEach(handler => handler(data))
}
}
function off(event, handler) {
if(eventList[event]) {
if(!handler) {
delete eventList[event]
}else {
let index = eventList[event].indexOf(handler)
eventList[event].splice(index, 1)
}
}
}
return {
on: on,
fire: fire,
off: off
}
})()
EventManager.on('sayHello', function(data) {
console.log('hello ' + data)
})
EventManager.fire('sayHello', 'Marshall')
两个模式的区别:
从表面上看:
- 观察者模式里,只有两个角色 —— 观察者 + 被观察者
- 而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker
往更深层次讲:
观察者和被观察者,是松耦合的关系
发布者和订阅者,则完全不存在耦合
从使用层面上讲:
观察者模式,多用于单个应用内部
发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件