前言
一直以来,都以为发布订阅模式和观察者模式是一个东西,直到无意看到一篇文章才知道,他们是有区别的~~~那他们的区别到底是什么呢?
发布订阅模式属于广义上的观察者模式
发布订阅模式是最常用的一种观察者模式的实现,并且从解耦和重用角度来看,更优于典型的观察者模式。
从代码看区别
发布订阅模式
let fs = require('fs');
let path = require('path');
let namePath = path.resolve(__dirname, 'name.txt');
let eagPath = path.resolve(__dirname, 'age.txt')
/**
* 发布 -> [中间代理] <- 订阅
* 发布和订阅两者之间没有任何关系,通过的都是中间代理。比如你想订一份麻辣烫,你不会去跟店家说,你会找外卖平台,跟外卖平台说我要订一碗麻辣烫。然后店家麻辣烫做好了,会通知外卖平台做好了,你可以送餐了。
*/
function Events() {
this.callbacks = [];
this.results = [];
}
// 订阅
Events.prototype.on = function(callback) {
this.callbacks.push(callback);
}
// 发布
Events.prototype.emit = function(data) {
this.results.push(data);
this.callbacks.forEach(v => v(this.results));
}
let e = new Events()
e.on(function(arr) {
if(arr.length === 2) {
console.log(arr)
}
})
/**
* 注意事项:
* 异步不能使用try catch
*/
fs.readFile(namePath, 'utf8', function(err, data) {
e.emit(data)
})
fs.readFile(eagPath, 'utf8', function(err, data) {
e.emit(data)
})
观察者模式
/**
* 观察者模式(vue是典型的观察者模式)
* 观察者有观察者和被观察者,如果被观察者数据变化了 会通知观察者 (是有关系的)
*/
// 被观察者 [被观察者中 要包括观察者]
// 比如我要观察我家小宝宝的心情 (心情好 || 心情不好)
class Subject {
constructor(name) {
this.name = name;
this.observers = []; // 观察者 要存放在被观察者中
this.state = '心情很美丽'
}
// 被观察者要提供一个接受观察者的方法
attach(observer) {
this.observers.push(observer); // 存放所有的观察者
}
setState(newState) { // 更改被观察者的状态
this.state = newState;
this.observers.forEach(v => v.update(newState))
}
}
// 观察者 (需要把观察者注册到被观察者中)
class Observer {
constructor(name) {
this.name = name;
}
update(newState) { // 用来通知所有的观察者状态更新了
console.log(`${this.name}说: 宝宝${newState}`)
}
}
let sub = new Subject('小宝宝');
let o1 = new Observer('爸爸');
let o2 = new Observer('妈妈');
sub.attach(o1);
sub.attach(o2);
sub.setState('心情不好了, 呜呜~~~');