Skip to main content

发布-订阅模式

CREATE: 2022-03-11 22:14:09

题目:请利用 Ts | Js 实现一个订阅-发布模式(或者称为发布-订阅模式) ( 简单😄 )

分析

注意区分 观察者模式订阅-发布模式,详见 观察者模式与订阅发布模式的区别

由下图可以发现,订阅-发布模式多了一个 中间人,负责订阅和发布

image-20220310225433851

题解

class PubCenter {
private subscribers: {
[type: string]: ((...args: any) => void)[]
} = {}

subscribe(type: string, fn: any) {
const topic = this.subscribers[type]

if (topic) {
topic.push(fn)
} else {
this.subscribers[type] = [fn]
}
}

publish(msg: any, type?: string) {
if (!type) {
Object.keys(this.subscribers).forEach((type) => {
this.publish(msg, type)
})
} else {
const topic = this.subscribers[type]

topic?.forEach((x) => x && x(`type:${type}, msg:${msg}`))
}
}

unsubscribe(type: string, fn: any) {
if (!type || !fn) return

const existIndex = this.subscribers[type]?.indexOf(fn)

if (existIndex != -1) {
this.subscribers[type].splice(existIndex, 1)
}
}

clear(type?: string) {
if (!type) {
this.subscribers = {}
} else {
this.subscribers[type] = this.subscribers[type] ? [] : undefined
}
}
}

使用

function main() {
const pubCenter = new PubCenter()

const fn1 = (msg) => {
console.log('[fn1 receive msg]:', msg)
}
const fn2 = (msg) => {
console.log('[fn2 receive msg]:', msg)
}
const fn3 = (msg) => {
console.log('[fn3 receive msg]:', msg)
}

pubCenter.subscribe('SMS', fn1)
pubCenter.subscribe('SMS', fn2)
pubCenter.subscribe('SMS', fn3)
pubCenter.subscribe('QQ', fn1)

pubCenter.publish('hello, everyone111')

console.log('[-----------unsubscribe fn2 SMS--------------]:')

pubCenter.unsubscribe('SMS', fn2)
pubCenter.publish('hello, everyone222')

console.log('[-----------clear all SMS--------------]:')

pubCenter.clear('SMS')
pubCenter.publish('hello, everyone333')
}

main()

输出

[fn1 receive msg]: type:SMS, msg:hello, everyone111
[fn2 receive msg]: type:SMS, msg:hello, everyone111
[fn3 receive msg]: type:SMS, msg:hello, everyone111
[fn1 receive msg]: type:QQ, msg:hello, everyone111
[-----------unsubscribe fn2 SMS--------------]:
[fn1 receive msg]: type:SMS, msg:hello, everyone222
[fn3 receive msg]: type:SMS, msg:hello, everyone222
[fn1 receive msg]: type:QQ, msg:hello, everyone222
[-----------clear all SMS--------------]:
[fn1 receive msg]: type:QQ, msg:hello, everyone333