发布订阅模式
大约 2 分钟约 625 字
定义
发布-订阅是⼀种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。⽽是将发布的消息分为不同的类别,⽆需了解哪些订阅者(如果有的话),同样的,订阅者可以表达对⼀个或多个类别的兴趣,只接收感兴趣的消息,⽆需了解哪些发布者存在。

优缺点
优点
- 解耦:发布-订阅模式可以使发布者和订阅者之间解耦,它们互不依赖于彼此的具体实现,从而降低组件之间的耦合度。
- 异步:发布-订阅模式支持异步操作,发布者可以在任何时间发布事件,订阅者也可以在适当的时间订阅事件。这种异步机制非常灵活,适用于需要非阻塞操作的场景。
- 动态:发布-订阅模式支持动态添加新的订阅者和取消订阅者,使得系统更加灵活和可扩展。
- 可复用性:通过发布-订阅模式可以实现事件的广播,可以让多个订阅者同时接收相同的事件消息,提高了代码的可复用性。
缺点
- 内存泄漏:发布-订阅模式在使用过程中需要手动管理订阅和取消订阅,如果不及时取消订阅可能会导致内存泄漏。
- 调试困难:因为事件的发布和订阅是分布式的,可能会导致事件流难以追踪,使得调试和代码理解变得困难。
- 性能问题:在一些多次触发事件的场景下,发布-订阅模式可能会存在性能问题,因为事件的广播需要循环遍历所有订阅者。
- 难以维护:在一个复杂的系统中,如果过度使用发布-订阅模式可能会导致事件流变得难以维护和理解,增加代码的复杂性。
实现
const PubSub = {
message: {},
publish(type) {
if (!this.message[type]) return
this.message[type].forEach((item) => item())
},
subscribe(type, cb) {
if (!this.message[type]) {
this.message[type] = [cb]
} else {
this.message[type].push(cb)
}
},
unsubscribe(type, cb) {
if (!this.message[type]) return
if (!cb) {
this.message[type] && (this.message[type].length = 0)
} else {
this.message[type] = this.message[type].filter(
(item) => item !== cb
)
}
},
}
function testA() {
console.log('testA')
}
function testB() {
console.log('testB')
}
function testC() {
console.log('testC')
}
PubSub.subscribe('A', testA)
PubSub.subscribe('A', testC)
PubSub.subscribe('B', testB)
PubSub.publish('A')
PubSub.publish('B')