天天看點

釋出訂閱設計模式-3- 面向對象設計模式

  /***

   * 

   *  建立多個事件池

   *    + 每個事件池是獨立的,存放自己訂閱的方法

   *    + 但是也可以具備共同的方法 on/off/fire

   *    => 面向對象中的類和執行個體

   */

  (function(){

    class Sub{

        // 執行個體私有屬性

       pond = [];

       // 原型公共方法

       on(func){

            let pond = this.pond; 

            !pond.includes(func) ? pond.push(func) : null;

       } 

       off(func){

         let pond = this.pond; 

         pond.forEach((item,index)=>{

             if(item === func){

                 pond[index] = null;

             }

         })

       }

       fire(...params){

        let pond = this.pond; 

        for(let i=0;i<pond.length;i++){

            let itemFunc = pond[i];

            if(typeof itemFunc !== "function"){

                // 移除 null 

                pond.splice(i,1);

                i--;

                continue;

            }

            itemFunc(...params);

        } 

    }

    window.subscribe = function sub(){

        return new Sub;

  })();

//====

 // 測試

 const fn1 = (x,y)=>{

    console.log('fn1',x,y); 

}

const fn2 = ()=>{

    console.log('fn2'); 

    sub1.off(fn1);

    sub1.off(fn2);

const fn3 = ()=>{

    console.log('fn3'); 

const fn4 = ()=>{

    console.log('fn4'); 

const fn5 = (x,y)=>{

    console.log('fn5',x,y); 

let sub1 = subscribe(),

    sub2 = subscribe();

    sub1.on(fn1) 

    sub1.on(fn2)

    sub1.on(fn3)

    sub1.on(fn4)

    sub1.on(fn5)

    sub2.on(fn1)  

    sub2.on(fn3) 

document.body.onclick = function () { 

    // 通知事件池的方法執行

    sub1.fire(10,20);

    sub2.fire(100,200);

 }