JavaScript设计模式(四):发布-订阅模式、观察者模式
定义
我们暂且把发布订阅模式和观察者模式理解成相同的,是行为型模式的一种,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
在日常生活中也有例子,例如我们办理银行卡时,如果订阅了手机短信功能,那么每次消费后都会给我们发送短信。
简单实现
我们先来简单模拟实现一个发布订阅模式。
1 |
|
以上代码通过 listeners 存放订阅信息,subscribe 方法来订阅信息,notify 方法来发布信息。
应用
EventBus
EventBus 就是基于发布-订阅模式实现的,由三个主要元素构成,事件、发布者、订阅者。
实现一个简易的 EventBus 需要几个关键因素
- 定义一个 tasks 来管理事件
- on 方法来订阅事件
- off 方法来退订
- once 方法只订阅一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47class EventBus {
constructor() {
// 初始化一个 tasks 存放事件名和对应的事件
this.tasks = {};
}
// 订阅事件
on(type, event) {
// 第一次订阅前先初始化
if (!this.tasks[type]) {
this.tasks[type] = [];
}
this.tasks[type].push(event);
}
// 发布
emit(type, ...rest) {
if (!this.tasks[type]) return;
// 循环执行所有回调
this.tasks[type].forEach(event => event(...rest));
}
// 取消订阅
off(type, event) {
if (!this.tasks[type]) return;
// 找到对应索引进行删除
const index = this.tasks[type].indexOf(event);
if (index !== -1){
this.tasks[type].splice(index, 1);
}
}
// 单次注册 执行完一次需要销毁
once(type, event) {
const that = this;
// 对原方法包装一下 在 _once 方法内执行 event 执行完就删除 订阅用的也是 _once 方法
function _once(...rest) {
event.apply(...arguments);
that.off(type, _once);
}
this.on(type, _once);
}
}
const tasks = new EventBus();
tasks.once('sayHello', () => console.log("Hello World"))
tasks.on('sayYes', ()=> console.log('yes'))
tasks.emit('sayHello')
tasks.emit('sayYes')
Redux
我们常用的状态管理工具 Redux 中就使用到了观察者模式,使用 subscribe 进行订阅,dispatch 进行发布。
发布订阅模式和观察者模式的区别
一句话简单解释就是发布订阅模式需要一个中间商,观察者模式不需要,形象化解释就是小组都需要一个文件,观察者模式就是领导直接把文件发送给你,发布订阅模式就是领导把文件放在某个公有文件夹中你自己去下载。另外如果是观察者模式,那么可能把所有文件都发给了你,而发布订阅模式,你就可以按需选择你用到的文件下载即可。
小结
发布-订阅模式应用的比较广泛,他帮助我们对模块间进行解耦,但同时也会会消耗空间内存,当你订阅了事件但从未触发,这个事件依旧占用着内存,造成浪费,所以合理使用也很重要。
JavaScript设计模式(四):发布-订阅模式、观察者模式
https://l1ushun.github.io/2023/10/13/design-observer/