观察者模式和发布订阅模式
前言
观察者模式和发布订阅模式其实是老生常谈的,但是我们进入vue的源码系列之后,肯定是需要接触到这个的,所以还是需要进行一些了解的
发布订阅、观察者 这两种设计模式的本质是相同的,但是还是由区别的
发布/订阅模式
- 订阅者
- 发布者
- 信号中心
我们假定,存在一个“信号中心”,某个任务知悉完成,就向信号中心“发布”(publish)一个信号,其他任务可以向信号中心 “订阅”(subscribe)这个信号,从而知道什么时候之间可以开始执行。这就叫做“发布\订阅模式”
举个比较简单的例子:
我参加了掘金的年度人气创作者榜单,并且获得了一等奖。
我很期待奖品,天天催着运营这么快递还不发货啊,还不发货啊。
那么现在我们可以直接关注快递的公众号,一旦掘金的运营通过对应的快递发货了,就会通过微信告诉我们,礼品发货了,礼品发货了!
这样其实就是一个发布订阅的过程,这个案例中
- 我 === 订阅者
- 运营 === 发布者
- 微信公众号 === 信号中心 这个概念还是有点抽象的,接下来我们通过代码来表现一下
代码实现
export class EventEmitter {
constructor() {
this.sub = {};
}
/**
*
* @param {*} methods 要注册的事件的事件名
* @param {*} handler 事件处理函数
*/
$on(methods, handler) {
if (!(methods in this.sub)) {
this.sub[methods] = [];
}
this.sub[methods].push(handler);
}
/**
*
* @param {*} methods 要触发的对应事件的事件名
* @param {*} param 对应事件函数的参数
*/
$emit(methods, param) {
if (methods in this.sub) {
this.sub[methods].forEach((element) => {
element(param);
});
}
}
}
观察者模式
- 观察者(订阅者) - Watcher
- update(): 当事件发生时,具体要做的事情
- 目标(发布者) - Dep
- subs数组: 储存所有的观察者
- addSub():添加观察者
- notify():当事件发生,调用所有观察者的update()方法
- 没有事件中心
代码实现
class Dep {
constructor() {
this.subs = [];
}
addSubs(sub) {
if (sub?.update) {
this.subs.push(sub);
}
}
notify() {
this.subs.forEach((sub) => {
sub.update();
});
}
}
class Watecher {
update() {
console.log("更新了");
}
}
const dep = new Dep();
const watecher = new Watecher();
dep.addSubs(watecher);
dep.notify(watecher);
总结
- 观察者模式是由具体目标调度,比如事件触发,Dep 就会去调用观察者的方法,所以观察者模式的订阅者与发布者之间是存在依赖的
- 发布/订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在