2020-03-20 發(fā)布-訂閱模式 EventEmitter

發(fā)布-訂閱模式,又稱觀察者模式。
一對多:當一個對象更新時,所有依賴它的對象都將得到通知并自動更新。
關鍵代碼:在抽象類里有一個 array list 來存放觀察者們。
關鍵概念:即使沒有觀察者,主體也可以獨自存在并正常運行。

主體“發(fā)布”事件。
觀察者通過“訂閱”事件來觀察對象。

優(yōu)點:
有助于解耦,保持功能的隔絕。
因為觸發(fā)事件的代碼和監(jiān)聽事件的代碼是完全分離的。

缺點:

  1. 如果觀察者和主體之間有循環(huán)依賴,系統(tǒng)會循環(huán)崩潰。
  2. 主體有很多直接/間接觀察者的話,通知到所有觀察者很花時間。
  3. 觀察者們不知道主體怎么發(fā)生變化,只知道它變了。

代碼1 - 紅寶書版:

function EventTarget() {
  this.handler = {}
}
EventTarget.prototype = {
  constructor: EventTarget,
  addHander(type, handler) {
    //增加事件
    if (typeof this.handler[type] == 'undefined') {
      this.handler[type] = []
    }
    this.handler[type].push(handler) //可能有很多方法,把方法做為數(shù)組
  },
  fire(event) {
    //觸發(fā)事件,傳入觸發(fā)的事件名和參數(shù)
    if (!event.target) {
      //如果沒有傳入事件對象,把實例做為對象
      event.target = this
    }
    //事件方法做為數(shù)組存在
    const handlers = this.handler[event.type]
    //if (handlers instanceof Array) {
    if (Array.isArray(handlers)) {
      const length = handlers.length
      for (let k = 0; k < length; k++) {
        handlers[k](event)
      }
    }
  },
  removeHander(type, handler) {
    //刪除事件
    const handlers = this.handler[type]
    //if (handlers instanceof Array) {
    if (Array.isArray(handlers)) {
      const length = handlers.length
      for (let k = 0; k < length; k++) {
        if (handlers[k] == handler) {
          this.handler[type].splice(k, 1)
          break
        }
      }
    }
  }
}
let event = new EventTarget()
function hello() {
  console.log('hi')
}
event.addHander('click', hello)
event.fire({
  type: 'click'
})

代碼2 - es6版:

// to do

調用代碼:

        function handleMessage(event){
            alert("Message received: " + event.message);
        }

        var target = new EventTarget();
        
        target.addHandler("message", handleMessage);

        target.fire({ type: "message", message: "Hello world!"});
        
        target.removeHandler("message", handleMessage);

        target.fire({ type: "message", message: "Hello world!"});

結合“寄生組合式繼承”(紅寶書p172):

        function Person(name, age){
            EventTarget.call(this);
            this.name = name;
            this.age = age;
        }
        
        inheritPrototype(Person,EventTarget);
        
        Person.prototype.say = function(message){
            this.fire({type: "message", message: message});
        };
        
        
        
        function handleMessage(event){
            alert(event.target.name + " says: " + event.message);
        }

        var person = new Person("Nicholas", 29);
        
        person.addHandler("message", handleMessage);
        
        person.say("Hi there.");
        function object(o){
            function F(){}
            F.prototype = o;
            return new F();
        }
            
        function inheritPrototype(subType, superType){
            var prototype = object(superType.prototype);   //create object
            prototype.constructor = subType;               //augment object
            subType.prototype = prototype;                 //assign object
        }

參考資料:

  1. 《紅寶書》第22章 高級技巧 - 自定義事件 p616 - 618
  2. 菜鳥教程 https://www.runoob.com/design-pattern/observer-pattern.html
  3. 霧切's blog 自定義事件/觀察者模式
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容