一、 什么是发布-订阅模式
-
定义:
发布订阅模式(Publish-Subscribe Pattern)是一种软件架构模式,用于实现一对多的依赖关系,其中一个对象(称为发布者)将消息发送给多个订阅者。在发布订阅模式中,发布者和订阅者之间是解耦的,发布者不需要知道订阅者的存在,订阅者也不需要直接与发布者交互。当发布者有新消息时,它将消息发送给一个中介(称为消息代理或事件总线),然后该中介将消息广播给所有订阅者。这种模式在解耦组件、实现事件驱动架构、异步通信等方面非常有用,常见应用场景包括消息队列、事件处理系统、UI框架等。
二、发布订阅模式的原理
- 发布订阅模式的原理是基于触发和监听机制。当一个对象(发布者)产生了某种事件或消息时,它不直接通知其他对象(订阅者),而是将该消息发送给一个中介(消息代理或事件总线)。订阅者可以向该中介注册感兴趣的事件类型,并提供相应的处理逻辑,中介负责将消息分发给所有订阅者。
原理步骤如下:
-
注册订阅:订阅者向消息代理注册感兴趣的事件类型,并提供相应的处理函数(回调函数)。
-
发布消息:发布者生成消息或事件,并将其发送给消息代理。
-
分发消息:消息代理接收到消息后,根据消息的类型将消息分发给所有订阅了该类型事件的订阅者。
-
处理消息:订阅者收到消息后,执行其注册的处理函数来处理消息,完成相应的操作。
通过这种触发和监听机制,发布订阅模式实现了发布者和订阅者之间的解耦,发布者不需要知道订阅者的存在,订阅者也不需要直接与发布者交互。这种松耦合的设计使得系统更易于扩展和维护,同时支持事件驱动架构和异步通信。
四、案例:
class PublishSubscriptionMode {
constructor() {
//创建一个对象 在该对象上创建一个缓存列表(调度中心)
this.list = {}
}
on(event, fn) {
//on 方法用来把函数 fn 都加到缓存列表中(订阅者注册事件到调度中心)
(this.list[event] || (this.list[event] = [])).push(fn)
return this;
}
emit() {
//emit 方法取到 arguments 里第一个当做 event,
//根据 event 值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理代码)
let event = [].shift.call(arguments);
if (this.list[event]) {
this.list[event].forEach(event => {
event.apply(this, arguments)
});
} else {
throw 'There is no such event'
return;
}
}
off(event, fn) {
//off 方法可以根据 event 值取消订阅(取消订阅)
if (!this.list[event]) return false;
if (!fn) {
this.list[event] && (this.list[event].length = 0);
} else {
let index = this.list[event].findIndex(v => v === fn)
this.list[event].splice(index, 1)
}
}
}
function u1(params) {
console.log(1, params)
}
function u2(params) {
console.log(2, params)
}
let bus = new PublishSubscriptionMode()
// 将方法进行注册
bus.on('ready', u1)
bus.on('ready', u2)
// 移出订阅 也就是取消订阅
bus.off('ready', u2)
// 触发调用
bus.emit('ready', '123')