发布订阅模式有很多名字,例如观察者模式.
观察者模式是一种行为设计模式,允许你定义一种订阅机制,可在对象事件发生时通知多个”观察”该对象的其他对象.
例子
发布订阅模式在编程里面很常见.下面举些例子.
javascrip
在js 里面经常用到的
- addEventListener
- dispatchEvent
- removeEventListener
websocket
- open
- message
- error
- close
1 | // Create WebSocket connection. |
Vue
- vm.$on
- vm.$once
- vm.$off
- vm.$emit
1
2
3
4
5vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
即时通信 IM SDK
- on
- off
1 | tim.on(TIM.EVENT.MESSAGE_RECEIVED, function(event) { |
核心内容
一个发布者,一个或多个订阅者
- 一个订阅的方法
- 一个发布的方法
- 一个取消订阅的方法
如何通用实现
也可以看 [JavaScript设计模式与开发实践] 这本书里面的 “第8章 发布—订阅模式”, 里面说的比较细1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69// event.js
class Event {
/**
* on 方法把订阅者所想要订阅的事件及相应的回调函数记录在 Event 对象的 _cbs 属性中
*/
on (event, fn) {
if (typeof fn != "function") {
console.error('fn must be a function')
return
}
this._cbs = this._cbs || {}
;(this._cbs[event] = this._cbs[event] || []).push(fn)
}
/**
* emit 方法接受一个事件名称参数,在 Event 对象的 _cbs 属性中取出对应的数组,并逐个执行里面的回调函数
*/
emit (event) {
this._cbs = this._cbs || {}
var callbacks = this._cbs[event], args
if (callbacks) {
callbacks = callbacks.slice(0)
args = [].slice.call(arguments, 1)
for (var i = 0, len = callbacks.length; i < len; i++) {
callbacks[i].apply(null, args)
}
}
}
/**
* off 方法接受事件名称和当初注册的回调函数作参数,在 Event 对象的 _cbs 属性中删除对应的回调函数。
*/
off (event, fn) {
this._cbs = this._cbs || {}
// all
if (!arguments.length) {
this._cbs = {}
return
}
var callbacks = this._cbs[event]
if (!callbacks) return
// remove all handlers
if (arguments.length === 1) {
delete this._cbs[event]
return
}
// remove specific handler
var cb
for (var i = 0, len = callbacks.length; i < len; i++) {
cb = callbacks[i]
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1)
break
}
}
return
}
}