设计模式|发布订阅模式
「奇怪?发布订阅模式并没在23种设计模式内?」
事实上发布订阅模式是观察者模式的一种变种,又或是说,发布订阅模式就是观察者模式。当然江湖上这个话题一直争论不休。要说区别,实际上就是发布订阅模式多了一个注册中心而已。
✍🏻定义
所谓定义就是最枯燥,最无聊的东西。诣在把一个东西说的高大上,今天比较懒,太多字了不想写。所以就略过吧,大家可以自己意淫或者等文末看看我有没有心情总结。
「好吧,让GPT写吧」
🙋♂️Q: 发布订阅模式是什么,能讲一下定义吗?
🤖GPT:
发布订阅模式(Publish-Subscribe Pattern)是一种消息传递模式,允许发送方(发布者)和接收方(订阅者)之间进行松耦合通信。通过这种模式,发布者不需要知道订阅者的存在,反之亦然。
发布订阅模式通过一个中介(通常称为事件总线或消息代理)来管理消息的发布和订阅。以下是该模式的核心要素:
- 发布者(Publisher):发布者将消息发送到中介,而不直接发送给订阅者。发布者只需要知道消息的类型,而不需要知道谁会接收这些消息。
- 订阅者(Subscriber):订阅者向中介注册自己感兴趣的消息类型。当相应的消息发布时,中介会通知所有订阅了该消息类型的订阅者。
- 中介(Mediator/Message Broker):中介负责管理消息的发布和订阅。它接收来自发布者的消息,并将这些消息传递给所有订阅了该消息的订阅者。
⚽️场景
发布订阅模式和观察者模式在实际场景中应用的很广泛。在常用的框架内也有很多体现。例如Vue中的watch
、computed
; 我们常用的各种消息总线,例如: bus总线
;Electron的IpcRenderer和IpcMain间的通信模式; 各种状态管理工具……太多了。
⭐️表现形式
在这篇文章中,我想使用Javascript
来展示,首先发布订阅模式是一种松耦合的设计模式。通常有两个角色:
- 发布者(Publisher): 负责发布事件或消息。
- 订阅者(Subscriber): 负责订阅事件或消息,并在事件发生时执行相应的操作。
发布者和订阅者可以是一对一
也可以是一对多
关系。
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
| class EventEmitter { constructor() { this.events = {}; }
on(event, listener) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(listener); }
emit(event, ...args) { if (this.events[event]) { this.events[event].forEach(listener => { listener(...args); }); } }
off(event, listener) { if (this.events[event]) { this.events[event] = this.events[event] .filter(l => l !== listener); } } }
const eventEmitter = new EventEmitter();
eventEmitter.on('message', data => { console.log('Received message:', data); });
eventEmitter.emit('message', 'Hello, world!');
|
这就是最基本的发布订阅模式结构。再来个实际的例子吧。
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
| class Child { constructor(name) { this.listeners = [] this.name = name }
addListener(listener) { this.listeners.push(listener) }
broadcast(event, msg) { this.listeners.forEach(listener => { if (!listener.events[event]) return listener.events[event](msg) }) } }
class Parent { constructor(name) { this.name = name this.events = {} } on(event, callback) { if (!this.events[event]) this.events[event] = callback } }
|
一个孩子和父母的例子,父母就是孩子的订阅者。孩子就是发布者。现在我们让孩子和他的发布者发生关系。
1 2 3 4 5
| const child = new Child('子涵'); const dad = new Parent('子涵爸爸'); const mom = new Parent('子涵妈妈'); child.addListener(dad); child.addListener(mom);
|
这对父母的孩子很聪明,叫做子涵。一天孩子哭了。
1 2 3 4 5 6 7 8 9 10 11 12 13
| mom.on('cry', (msg) => { console.log('别哭了宝贝,妈妈这就来了') }) dad.on('cry', (msg) => { console.log('别哭了傻种,爸爸来打你了') })
child.broadcast('cry', '我好饿')
|
于是,在得到父母的关爱后,子涵立马不哭了。这就是一个发布订阅模式的例子。孩子作为事件的发布者,维护了事件中心。父母作为事件的订阅者,监听孩子发布/广播的数据。当然,广播的粒度也可以自定义。
好了,今天的的博客就到这吧……等我下回心血来潮了再来继续写吧。
🫵未完待续;
技术分享 — 2024年5月16日