设计模式:发布订阅模式

简单的来说,就是将引用数据对象的对象作为订阅者,存放在数据对象的订阅者队列中或指定的缓存位置,当数据对象发生变化时,通过遍历订阅者队列通知订阅者数据的变化。

这种模式的存在解决了一些场景:例如需要轮询是否发生变化,这对性能无疑是一种浪费(但轮询可以做到主动索取,能避免通知失败的情况)

由于是以推送的形式去通知订阅者,所以该模式可以广泛应用于异步编程中,是一种回调函数的代替方案。该模式也能解耦发布者和订阅者,彼此不需要关注对方有何更改。

DOM事件的绑定就是发布订阅的实现,发布者为DOM,订阅者为listener。

当实现发布订阅模式时,需要关注如下三点

  1. 指定发布者
  2. 维护一个订阅者集合,收集、删除等操作
  3. 发布时遍历集合通知订阅者,或执行订阅者的回调

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let publisher = {};

publisher.subscribeList = [];

publisher.addSubscribe = function(fn){
this.subscribeList.push(fn);
};

publisher.notify = function(){
this.subscribeList.forEach(function(fn){
fn.apply(this, arguments);
},this)
};

publisher.addSubscribe(function(){
console.log('first subscriber',this)
});

publisher.addSubscribe(function(){
console.log('first subscriber')
});

publisher.notify();

为了能够更好的区分订阅者订阅的消息种类(那部分数据发生了变化),在添加订阅者队列时可以指定key值标识

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
publisher.subscribeList = {};
publisher.addSubscribe = function(key, fn){
if(!this.subscribeList[key]){
this.subscribeList[key] = [];
}
this.subscribeList.push(fn);
}

publisher.notify = function(...args){
const [key, ...params] = [...ages];
const fns = this.subscribeList[key];
if(!fns){
return false;
}
fns.forEach(function(){
fn.apply(this, params);
})
}

设计模式:发布订阅模式

http://example.com/2022/11/04/发布订阅模式/

作者

徐云飞

发布于

2022-11-04

更新于

2023-02-05

许可协议

评论