设计模式之发布-订阅模块

384 阅读2分钟

发布-订阅模式

发布-订阅模式和观察者模式的工作方式很相近,一个区别是,观察者模式种,观察者直接从它所观察的试题那里得到通知,而在发布-订阅模式,订阅者通过渠道得到通知,渠道位于发布者和订阅者之间来回传递信息。

jquery的发布-订阅方法

//开辟一个容器
let container = $.callBack();
//往容器里面订阅函数事件
container.add(function(){
    console.log("订阅事件")
})
//发布事件
container.fire(function(){
    console.log("发布事件")
})
//移除事件
container.remove(function(){
    console.log("移除事件")
})

手动实现发布-订阅模式

class Subscribe{
    constructor(){
        //创建一个事件池,用来存储需要执行的方法
        this.pond = [];
    }
    add(fn){
        let flag = this.pond.some(item =>{
            return item === fn;
        })
        !flag ? this.pond.push(fun) : null;
    }
    remove(fn){
        let pnd = this.pond;
        pond.forEach((item,index) =>{
            if(item === fn){
                //设置item = null 是无效的
                pond[index] = null;
            }
        })
    }
    fire(...arg){
        let pond = this.pond;
        for(let i=0;i<pond.length;i++){
            //如果item为null,则把它删除
            if(item === null){
                 //防止使用循环中使用splice,数组塌陷问题,即删除一个元素后,后面所有元素的索引默认都会减1
                pond.splice(i,1);
                i--;
                continue;
            }
            item(...arg);
        }
    }
}
let subscribe = new Subscribe();
let fn1 = function fn1(){
    console.log("注册事件1")
}
let fn2 = function fn2(){
    console.log("注册事件2")
}
subscribe.add(fn1)
subscribe.add(fn2)
subscribe.fire()
//订阅两个事件,事件1和事件2,发布会按顺序执行两个事件
//打印结果
//注册事件1
//注册事件2

//移除事件事件1
subscribe.remove(fn1)
subscribe.fire()
//打印结果
//注册事件2

踩坑记录

数组塌陷问题

什么是数组塌陷

在对数组进行遍历循环等操作时,会使数组的长度产生变化,同时操作的数组那个项的下一个索引会被跳过,从而造成数组的某项会被跳过,这种叫做数组塌陷现象。

注意:删除后数组的索引还是保持连续的。

解决方法

  1. 索引自减1
let arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {
    arr.splice(i, 1);
    i--;
}
  1. 由后往前循环(不推荐)
let arr = [1, 2, 3, 4];
for (let i = arr.length - 1; i >= 0; i--) {
   arr.splice(i, 1);
 }

但是又引入新问题,遍历后时执行顺序时颠倒的,不太符合我们的预期,之后针对这情况需要进一步处理。如执行前先反转数组。

发布订阅模式和观察者模式区别

参考文章

1.基于"发布-订阅"的原生JS插件封装