发布订阅模式的优缺点
优点
- 广泛应用于异步编程中,先订阅某个请求的某个事件,当这个事件触发时就会执行订阅的事件处理函数
- 发布订阅模式可以取代通过硬编码的对象通知机制,不需要显式地调用另一个对象的接口,减少对象之间的耦合
发布订阅模式的一般步骤
- 定义发布者
- 给发布者指定缓存列表,用于存储回调函数以便通知订阅者
- 最后发布消息的时候,发布者会遍历这个缓存列表,依次触发回调函数
示例:售楼
let saler = {
clientList:[]
}
saler.listen = function (fn){
this.clientList.push(fn);
}
saler.trigger = function (){
for(let i = 0; i < this.clientList.length; i++){
this.clientList[i](...arguments);
}
}
saler.listen(function (price, square) {
console.log(price, square);
});
saler.trigger(2000, 100);
这种方式使得所有的订阅者都会接收到所有的事件,即便不是自己订阅的事件。因此,将其进行修改为以下方式:
let saler = {
clientList:{}
}
saler.listen = function (key, fn){
if(!this.clientList[key]){
this.clientList[key] = [];
}
this.clientList[key].push(fn);
}
saler.trigger = function (key){
if(this.clientList[key]){
let fns = this.clientList[key];
for (let i = 0; i < fns.length; i++) {
fns[i](...arguments);
}
}
}
saler.remove = function (key, fn){
let fns = this.clientList[key];
if(!fns){
return;
}
if(!fn){
fns &&( fns.length = 0);
} else {
for(let i = 0; i < fns.length; i++){
if(fns[i] === fn){
fns.splcie(i, 1);
}
}
}
}
saler.listen('a', fn1 = function (key, ars) {
console.log(key, ars)
})
saler.trigger('a', 100);
saler.remove('a', fn1);
这种方式订阅者只会接收到自己订阅的事件,并且还可以对自己订阅的事件进行解除订阅。
观察者模式可以用来解决模块间的通信问题,使用之前需要明确哪些模块需要订阅消息,哪些模块需要发布消息。