观察者模式时软件设计模式的一种。
在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。

我们要实现用邮件订阅一个数据库,然后数据库有更新时就向我们发布信息。因此要实现:

一个方法用于订阅————subscribe
一个方法用于发布————publish
一个方法用于取消订阅————unSubscribe
一个用来存储我们订阅信息的数据“注册表”对象————store

1
2
3
4
5
6
let publisher = {
store: {},
subscribe: function (type, fn) {},
unSubscribe: function (type, fnName) {},
publish: function (type, message) {}
}
  • store把它设计成一个对象是因为考虑到可能有更多类型的数据,比如 游戏,金融,投资理财等等,所以就把它设计成对象以key-value的形式存储订阅者, 比如:{‘game’:[],’monetary’:[]}该形式
  • subscribe 则是publisher提供给我们的对其进行订阅的方法,参数是type和 fn。type就是我们订阅的类型,fn就是我们提供给publisher用于通知我的渠道 (邮箱)。在JavaScript中更多的是回调函数。
  • unSubscribe 是publisher提供给我们的对其进行取消订阅的方法,参数是type和 fnName。type就不多说了,fnName则是我们提供给publisher用于取消订阅的标志,比如说邮箱,或者是回调函数的名字等等。
  • publish说到比较重要的方法,这就是publisher向所有订阅者发布消息的方法。
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
let publisher = {
store: {},
subscribe: function (type, fn) {
if (Object.keys(this.store).indexOf(type) >= 0) {
this.store[type].push(fn);
} else {
this.store[type] = [];
this.store[type].push(fn);
}
},
unSubscribe: function (type, fnName) {
if (Object.keys(this.store).indexOf(type) >= 0) {
let index = -1;
this.store[type].forEach(function (func, idx) {
if (func.name === fnName) {
index = idx;
}
})
index > -1 ? this.store[type].splice(index, 1) : null
}
},
publish: function (type, message) {
if (Object.keys(this.store).indexOf(type) >= 0) {
for (let fn of this.store[type]) {
fn(message)
}
}
}
}

进行调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let subscriberA = function (message) {
console.log(`A收到通知:${message}`)
};

let subscriberB = function (message) {
console.log(`B收到通知:${message}`)
};

let subscriberC = function (message) {
console.log(`C收到通知:${message}`)
};

publisher.subscribe('game', subscriberA);
publisher.subscribe('game', subscriberB);
publisher.subscribe('game', subscriberC);

publisher.publish('game', 'we play')

再取消订阅

1
publisher.unSubscribe('game', subscriberB.name)

B就接收不到数据了。