js 发布订阅者模式 and 观察者模式

定义:发布-订阅模式

Publish/Subscribe pattern和Observer pattern和类似,都是Observer注册,subject分布通知,但是Publish/Subscribe pattern多了个事件管道(event channel)用来集中处理监听的事件

观察者模式

观察者是一种 包含一系列依赖于主体(subject)的观察者(observers),自动通知它们变化的内容的设计模式,通俗来说就是一个对象(称为subject)维持一系列依赖于它的对象(称为observer),将有关状态的任何变更自动通知给它们(观察者)

区别
image

如上图所示在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。

代码实现例子
观察者模式
//观察者列表
function ObserverList(){
  this.observerList = [];
}
ObserverList.prototype.add = function( obj ){
  return this.observerList.push( obj );
};
ObserverList.prototype.count = function(){
  return this.observerList.length;
};
ObserverList.prototype.get = function( index ){
  if( index > -1 && index < this.observerList.length ){
    return this.observerList[ index ];
  }
};
ObserverList.prototype.indexOf = function( obj, startIndex ){
  var i = startIndex;
  while( i < this.observerList.length ){
    if( this.observerList[i] === obj ){
      return i;
    }
    i++;
  }
  return -1;
};
ObserverList.prototype.removeAt = function( index ){
  this.observerList.splice( index, 1 );
};

//目标
function Subject(){
  this.observers = new ObserverList();
}
Subject.prototype.addObserver = function( observer ){
  this.observers.add( observer );
};
Subject.prototype.removeObserver = function( observer ){
  this.observers.removeAt( this.observers.indexOf( observer, 0 ) );
};
Subject.prototype.notify = function( context ){
  var observerCount = this.observers.count();
  for(var i=0; i < observerCount; i++){
    this.observers.get(i).update( context );
  }
};

//观察者
function Observer(){
  this.update = function(){
    // ...
  };
}
发布-订阅模式
//发布订阅模式
class EventEmiter {
    constructor() {
        //维护一个对象
        this._events = {};
    }
    on(eventName, callback) {
        if (this._events[eventName]) {
            //如果有就放一个新的
            this._events[eventName].push(callback);
        } else {
            //如果没有就创建一个数组
            this._events[eventName] = [callback];
        }
    }
    emit(eventName, ...rest) {
        if (this._events[eventName]) {
            //循环一次执行
            this._events[eventName].forEach(item => {
                item.apply(this, rest);
            });
        }
    }
    removeListener(eventName, callback) {
        if (this._events[eventName]) {
            //当前数组和传递过来的callback相等则移除掉
            this._events[eventName] = this._events[eventName].filter(item => item !== callback);
        }
    }
    once(eventName, callback) {
        function one() {
            //在one函数运行原来的函数,只有将one清空
            callback.apply(this, arguments);
            //先绑定 执行后再删除
            this.removeListener(eventName, one);
        }
        this.on(eventName, one);
        //此时emit触发会执行此函数,会给这个函数传递rest参数
    }
}
class Man extends EventEmiter {}
let man = new Man();
function findGirl(a) {
    console.log(a + '找新的女朋友');
}
function saveMoney(b) {
    console.log(b + '省钱');
}
man.on('失恋', findGirl);
// man.on('失恋', findGirl); //失恋 ,绑定一个函数方法
man.on('失恋', saveMoney); //失恋 ,绑定一个函数方法
// man.removeListener('失恋', saveMoney); //移除一个函数方法
man.emit('失恋', { a: 1, b: 3 });
//绑定一次,触发多次,也只执行一次。触发后一次将数组中的哪一项删除掉下次触发就不会执行

你可能感兴趣的:(js 发布订阅者模式 and 观察者模式)