写一个最简发布订阅模式

913 阅读2分钟

什么是发布订阅模式?

软件架构中,发布订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

怎样实现一个最简发布订阅?

发布订阅里其实只有 3 个重要的东西:

  • 一个数组订阅者
  • 一个方法添加订阅者
  • 一个方法通知订阅者

以下是一个最简发布订阅的实现,便于理解

function Subscribe(){
    this.listenerArr = []   // 用来存订阅者
    // 存订阅者的方法
    this.addListener = (listener) => {
        this.listenerArr.push(listener)
    }
    // 发布的方法
    this.notify = (fn) => {
        this.listenerArr.forEach((listener)=>{
            fn(listener)
        })
    }
}

let s1 = new Subscribe()  // 创建一个实例

s1.addListener('小明')  // 小明订阅了
s1.addListener('小红')  // 小红订阅了
s1.addListener('小蓝')  // 小蓝订阅了

s1.notify((name)=>{
    console.log(`${name}去吃饭`)    // 让他们都去吃饭
})

s1.notify((name)=>{
    console.log(`${name}去散步`)    // 让他们都去散步
})

打印:

image.png

也可以这么理解,listenerArr相当于一个公众号的粉丝,addListener方法相当于用户关注了这个公众号,notify相当于这个公众号发布了一篇文章告诉粉丝去看。

扩展

你发现没有,上面的订阅者都是人,其实也可以是方法,比如这样写。

function Subscribe(){
    this.listenerArr = []   // 用来存订阅者
    this.addListener = (listener) => {
        this.listenerArr.push(listener)
    }
    this.notify = (name) => {
        this.listenerArr.forEach((listener)=>{
            listener(name)
        })
    }
}

let s1 = new Subscribe()  // 创建一个实例

s1.addListener((name) => {
    console.log(`${name}去吃饭`)
}) 

s1.addListener((name) => {
    console.log(`${name}去散步`)
}) 

s1.notify('小明')

打印:

image.png

总结

核心就是用一个数组存,一个方法添加,一个方法通知。

这些地方用到了发布订阅:Promise的原理实现,Vue里EventBus$on$off

题外话,怎样区分发布订阅和观察者模式:
观察者模式 在软件设计中是一个对象,维护一个依赖列表,当任何状态发生改变自动通知它们。
发布-订阅模式,消息的发送方,叫做发布者(publishers),消息不会直接发送给特定的接收者,叫做订阅者(Subscriber)