第33题 实现一个发布订阅者模式

简介:

发布订阅者模式,一种对象间一对多的依赖关系,但一个对象的状态发生改变时,所依赖它的对象都将得到状态改变的通知。

主要的作用(优点):

  1. 广泛应用于异步编程中(替代了传递回调函数)
  2. 对象之间松散耦合的编写代码

缺点:

  • 创建订阅者本身要消耗一定的时间和内存
  • 多个发布者和订阅者嵌套一起的时候,程序难以跟踪维护

实现的思路:

  • 创建一个对象(缓存列表)
  • on方法用来把回调函数fn都加到缓存列表中
  • emit方法取到arguments里第一个当做key,根据key值去执行对应缓存列表中的函数
  • remove方法可以根据key值取消订阅

coding:

    let event = {
      list: {},
      on (key, fn) {
        if (!this.list[key]) {
          this.list[key] = [];
        }
        this.list[key].push(fn);
      },
      emit () {
        let key = [].shift.call(arguments),
          fns = this.list[key];
        if (!fns || fns.length <= 0) {
          return false;
        }
        fns.forEach(fn => {
          fn.apply(this, arguments);
        })
      },
      remove (key, fn) {
        let fns = this.list[key];
        if (!fns || fns.length <= 0) {
          return false;
        }
        if (!fn) {
          fns && (fns.length = 0);
        } else {
          fns.forEach((cb, i) => {
            if (cb === fn) {
              fns.splice(i, 1);
            }
          })
        }
      }
    }
    function cat () {
      console.log('喵喵喵~');
    }
    function dog () {
      console.log('汪汪汪~');
    }
    function hasArgs (args) {
      console.log(args);
    }
    event.on('pet', hasArgs);
    event.on('pet', cat);
    event.on('pet', dog);
    
    event.remove('pet', dog)
    
    event.emit('pet', '我是传递的参数');
    
    // 结果:
    // '我是传递的参数'
    // '喵喵喵~'

工作中的应用:

  • 插广告
  • 打点

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

  • 发布/订阅模式是观察者模式的一种变形,两者区别在于,发布/订阅模式在观察者模式的基础上,在目标和观察者之间增加一个调度中心。
  • 观察者模式 是由具体目标调度,比如当事件触发,Subject 就会去调用观察者的方法,所以观察者模式的订阅者与发布者之间是存在依赖的。
  • 发布/订阅模式 由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。
Last Updated:
Contributors: leeguooooo