第一版
// 发布者类
class Publisher {
constructor(){
this.subs = []
}
// 消息订阅
addSub(...subs) {
subs.forEach(sub => {
this.subs.push(sub)
})
}
// 消息发布
notify() {
this.subs.forEach( sub => {
sub.update()
})
}
}
// 创建发布者
const p = new Publisher();
// 创建订阅者
const s1 = {
name: 's1',
update(){
console.log(`I am ${this.name}`)
}
}
const s2 = {
name: 's2',
update(){
console.log(`I am ${this.name}`)
}
}
const s3 = {
name: 's3',
update(){
console.log(`I am ${this.name}`)
}
}
// 订阅者订阅发布者
p.addSub(s1,s2,s3);
// 发布者发布消息
p.notify()
// 输出结果
I am s1
I am s2
I am s3
这样就实现了一个最简单的订阅发布模型,订阅者订阅了发布者之后,不需要实时观察发布者的变化,一旦发布者有任何的变化,就会通知所有订阅了它的订阅者们,类似于微信公众号,我们订阅了某个微信公众号,并不需要一直去看该订阅号有没有更新,因为一旦该订阅号更新了,就会向所有订阅了它的用户们发出通知,订阅者们自然也就收到了订阅号的发布。
第二版、增加参数
// 发布者类
class Publisher {
constructor() {
this.subs = []
}
// 消息订阅
addSub(...subs) {
subs.forEach(sub => {
this.subs.push(sub)
})
}
// 消息发布
notify(...payload) {
this.subs.forEach(sub => {
sub.update(payload)
})
}
}
// 创建发布者
const p = new Publisher();
// 创建订阅者
const s1 = {
name: 's1',
update(payload) {
console.log(`I am ${this.name}, I like ${payload}`);
}
}
const s2 = {
name: 's2',
update(payload) {
console.log(`I am ${this.name}, I like ${payload}`);
}
}
const s3 = {
name: 's3',
update(payload) {
console.log(`I am ${this.name}, I like ${payload}`);
}
}
// 订阅者订阅消息
p.addSub(s1,s2,s3)
// 发布者发布消息
p.notify('eating','reading','...')
第三版、区分类型
// 发布者类
class Publisher {
constructor() {
this._subsMap = {}
}
// 订阅消息
addSub(...subs) {
subs.forEach(sub => {
if (this._subsMap[sub['type']]) {
this._subsMap[sub['type']].push(sub)
} else {
this._subsMap[sub['type']] = [sub]
}
})
}
// 发布消息
notify(type,...payload) {
this._subsMap[type].forEach( sub => {
sub.update(payload)
})
}
}
// 创建发布者
const p = new Publisher();
// 创建订阅者
const s1 = {
name: '小米',
type: 'eating',
update(payload) {
console.log(`${this.name} get a message: ${payload}`);
}
}
const s2 = {
name: '腾讯',
type: 'eating',
update(payload) {
console.log(`${this.name} get a message: ${payload}`);
}
}
const s3 = {
name: '阿里',
type: 'reading',
update(payload) {
console.log(`${this.name} get a message: ${payload}`);
}
}
// 订阅者订阅发布者
p.addSub(s1, s2, s3)
// 发布者发布特定类型消息
p.notify('reading','article about reading is update,read it by now~');
p.notify('eating','you are hungry,eating something now~');
// 输出结果
阿里 get a message: article about reading is update,read it by now~
小米 get a message: you are hungry,eating something now~
腾讯 get a message: you are hungry,eating something now~
第四版、一些小的优化(订阅者成类,退订功能)
// 发布者类
class Publisher {
constructor() {
this._subsMap = {}
}
// 订阅
subscribe(...subs) {
subs.forEach(sub => {
if (this._subsMap[sub['type']]) {
this._subsMap[sub['type']].push(sub)
} else {
this._subsMap[sub['type']] = [sub]
}
})
}
// 退订
unSubscribe(...subs) {
subs.forEach(sub => {
// 该订阅者未订阅发布者
if (!this._subsMap[sub['type']].includes) return;
this._subsMap[sub['type']].forEach((minSub, index) => {
if (sub['name'] === minSub['name']) {
this._subsMap[sub['type']].splice(index, 1)
return;
}
})
})
}
// 发布
notify(type, ...payload) {
this._subsMap[type].forEach(sub => {
sub.update(payload)
})
}
}
// 订阅者类
class Subscribe {
constructor(name, type) {
this.name = name
this.type = type
}
update(payload) {
console.log(`${this.name} get a message: ${payload}`);
}
}
// 创建发布者
const p = new Publisher();
// 创建订阅者
const s1 = new Subscribe('小米', 'eating')
const s2 = new Subscribe('腾讯', 'eating')
const s3 = new Subscribe('阿里', 'reading')
const s4 = new Subscribe('头条', 'sleeping')
p.subscribe(s1, s2, s3, s4)
p.notify('reading', 'article about eating is update,read it by now~');
p.notify('eating', 'you are hungry,eating something now~');
p.notify('sleeping', 'sleeping now~');
p.unSubscribe(s2, s4)