发布订阅模式
发布订阅模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。通过它,不必定时的去查询监听对象的状态是否发生改变。
在发布订阅模式中,我们经常定义一个事件中心来管理所有事件的发布和订阅。这也是和观察者模式最主要的区别。
观察者模式中只有两个角色,观察者和被观察者,两者之间存在一定的耦合关系。发布订阅模式,则有三个角色,发布者、订阅者和事件中心。事件中心可以避免发布者和订阅者之间的依赖关系,它一方面从发布者处接收事件,一方面向订阅者发布事件。
观察者模式:
╭─────────────╮ Fire Event ╭──────────────╮
│ │─────────────>│ │
│ Subject │ │ Observer │
│ │<─────────────│ │
╰─────────────╯ Subscribe ╰──────────────╯
发布订阅模式:
╭─────────────╮ ╭───────────────╮ Fire Event ╭──────────────╮
│ │ Publish Event │ │───────────────>│ │
│ Publisher │────────────────>│ Event Channel │ │ Subscriber │
│ │ │ │<───────────────│ │
╰─────────────╯ ╰───────────────╯ Subscribe ╰──────────────╯
下面是一个事件中心的实现:
const Event = (function () {
const clientList = {}
const listen = function (key, fn) {
if ( !clientList[key] ) {
clientList[key] = []
}
clientList[key].push( fn )
}
const trigger = function () {
const key = Array.prototype.shift.call( arguments )
const fns = clientList[key]
if (!fns || fns.length === 0) {
return
}
for (let i = 0, listener;listener = fns[i++];) {
listener.apply(this, arguments)
}
}
const remove = function (key, fn) {
const fns = clientList[key]
if (!fns || fns.length === 0) {
return
}
const index = fns.indexOf(fn)
if (index !== -1) {
fns.splice(index, 1)
}
}
return {
listen,
trigger,
remove
}
})()
function onMessage1() {
console.log('message 1')
}
function onMessage2() {
console.log('message 2')
}
Event.listen('message', onMessage1)
Event.listen('message', onMessage2)
Event.trigger('message')
// message 1
// message 2
Event.remove('message', onMessage1)
Event.trigger('message')
// message 2