设计模式学习(二):发布-订阅模式
什么是发布-订阅模式
发布-订阅模式又叫观察者模式,它定义对象间的一对多的依赖关系,当一个对象的状态发生变化时,所有订阅它的对象都将得到通知;实现发布-订阅模式有以下几步:
- 首先要指定好谁充当发布者;
- 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者;
- 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数。
代码实现
// event.js
let event = {
clientObj: {},
/**
* @param {string} key
* @param {function} fn
*/
subscribe: function (key, fn) {
if (!this.clientObj[key]) {
this.clientObj[key] = []
}
this.clientObj[key].push(fn)
},
publish: function () {
let key = Array.prototype.shift.call(arguments)
let fns = this.clientObj[key]
if (!fns || !fns.length) {
return false
}
fns.forEach(fn => {
fn.apply(this, arguments)
})
},
/** @param {string} key */
unSubscribe (key) {
this.clientObj[key] = []
},
unSubscribeAll () {
this.clientObj = {}
},
}
/**
* @describe 维护一个方法,为对象安装发布-订阅功能
*/
export const EventMitt = function (obj) {
for (let key in event) {
obj[key] = event[key]
}
}
// 使用,index.js
import { EventMitt } from './event.js'
let event = {}
EventMitt(event)
event.subscribe('flag1', (val) => {
console.log(val) // test1
})
event.subscribe('flag2', (val) => {
console.log(val) // test2
})
event.publish('flag1', 'test1')
event.publish('flag2', 'test2')
用ES6来重写这个发布-订阅模式
// event.js
export class EventMitt {
/** @private */
constructor () {
this.clientObj = {}
}
publish () {
let key = Array.prototype.shift.call(arguments)
let fns = this.clientObj[key]
if (!fns || !fns.length) {
return false
}
fns.forEach(fn => {
fn.apply(this, arguments)
})
}
/**
* @param {string} key
* @param {function} fn
*/
subscribe (key, fn) {
if (!this.clientObj[key]) {
this.clientObj[key] = []
}
this.clientObj[key].push(fn)
}
/** @param {string} key */
unSubscribe (key) {
this.clientObj[key] = []
}
unSubscribeAll () {
this.clientObj = {}
}
}
// 使用,index.js
import { EventMitt } from './event.js'
const eventMitt = new EventMitt()
eventMitt.subscribe('flag1', (val) => {
console.log(val) // test1
})
eventMitt.subscribe('flag2', (val) => {
console.log(val) // test2
})
eventMitt.publish('flag1', 'test1')
eventMitt.publish('flag2', 'test2')
参考:
《JavaScript设计模式与实践开发》
浙公网安备 33010602011771号