设计模式尝试(策略模式、代理模式、发布订阅者模式、职责链模式)---js实现

   策略模式:个人感觉就是简单的将不同的方法封装起来,对外暴露一个统一的入口,这样方便使用不同的逻辑。

class choiceItem {
    static getMoney(type, base) {
        switch(type) {
            case 's' : 
                return this.sType(base);
            case 'a' : 
                return this.aType(base);
            case 'b' : 
                return this.bType(base);
        }
    }
    static sType(base) {
        return 6*base; 
    }
    static aType(base) {
        return 4*base;    
    }
    static bType(base) {
        return 2*base;
    }
}
console.log(choiceItem.getMoney('s', 1000));

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

   代理模式:作为比较经典的模式应用起来其实并不困难,原理大概就是委托另一方去做某件事情。这个另一方可以增加某些判断,也就是说在不修改原有逻辑的前提下又增加了某些特定功能,例如最最经典的图片代理缓存。

class imgLoad{
  constructor(url, loUrl, dom, proxy) {
    this.url = url;
    this.proxy = proxy;
    this.dom = dom;
    this.loUrl = loUrl;
    if(this.proxy) {
      this.isIma = this.isImage();
      this.proxyIma = this.proxyImage();
      this.proxyIma.setSrc.call(this, this.url);
    } else {
      this.isIma = this.isImage();
      this.isIma.setSrc.call(this, this.url);
    }
  }
  isImage() {    //  正常图片添加区域
    const img = new Image();
    this.dom.appendChild(img);
    return {
      setSrc(url) {
        img.src = url;
      }
    }
  }
  proxyImage() {  //  缓存图片
    const img = new Image();
    img.onload = () => {
      this.isIma.setSrc(this.url);
    }
    return {
      setSrc: function(url) {
        img.src = url;
        this.isIma.setSrc(this.loUrl);
      }
    }
  }
}

new imgLoad('http://ali-static.game.yximgs.com/bs2/fes/game_1571312642677_.png', 'http://ali-static.game.yximgs.com/bs2/fes/game_1571311087230_.png', document.body, true);

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

  发布订阅者模式:实际上就是js中的event,注册一个事件,然后在某个特定时间点进行触发,很多的框架使用的时候都利用了这个方法,例如vue组件间触底方法的时候实际上就是这个发布订阅者模式生成的效果。

class Event {
    constructor() {
        this.eventList = {};
    }

    on(type, fn) {
        if(!this.eventList[type]) {
            this.eventList[type] = [];
        }
        this.eventList[type].push(fn);
    }

    emit() {
        const type = Array.prototype.shift.call(arguments);
        const arr = this.eventList[type];
        for(let i in arr) {
            arr[i].apply(arr[i], arguments);
        }
    }
}

const ev1 = new Event();

ev1.on('ceshi', function(a,b,c) {
    console.log(a);
    console.log(b);
    console.log(c);
})

ev1.emit('ceshi', '1111', '2222', '3333');

  注意上方代码实际上并没有完全实现on、emit触发,如果触发在on之前的话就会出错。作为容错处理可以在emit中每次触发如果不存在时,将其保存在一个队列中,然后再on中注册是检查是否存在该新增的,然后进行触发,当然这只是简单的逻辑,其中肯定也要包括更多各种各样的容错处理。在此就不多说了。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

  职责链模式:一个理解起来蛮简单,实现起来稍微麻烦点的模式。这个模式主要用于将类似,但是职责不同的代码分开。核心在于,每个当前处理自己阶段的方法,不关心下一个方法处理的具体内容。利用链式处理将多个判断来进行分化。

  例如我们想要提取166块钱。那么首先是先扣除面额为100元的钱,然后扣除面额为50,依次类推直到将所有的钱都计算成不同面额现金吐出。

class moneySize { // 生成面额不同的钱
  constructor(size) {
    this.size = size;
    this.next = null;
  }
  getMoney(money) {
    const floorMoney = Math.floor(money / this.size);
    if(floorMoney > 0) {
      console.log(this.size+'元:此处吐出'+floorMoney*this.size);
      money = money - (floorMoney*this.size);
    }
    money>0 && this.next && this.next.getMoney(money);
  }
  setNext(next) {
    this.next = next;
  }
}

class ATM {   // atm机,主要进行职责链的拼接,以及金额的设定
  constructor() {
    this.money100 = new moneySize(100);
    this.money50 = new moneySize(50);
    this.money20 = new moneySize(20);
    this.money10 = new moneySize(10);
    this.money1 = new moneySize(1);

    this.money100.setNext(this.money50);
    this.money50.setNext(this.money20);
    this.money20.setNext(this.money10);
    this.money10.setNext(this.money1);

    this.first = this.money100;
  }

  setMoney(money) {
    this.first.getMoney(money);
  }
}

const atm = new ATM();

atm.setMoney(166);

  需要注意的是,职责链模式虽然可以无限拼接。但是在处理的时候造成比较大浪费,例如我们假设想要获取6元钱,那么它会浪费掉前期的100、50等等面额的计算,最终确定在1元的金额进行处理。所以这个本身是存在浪费的,所以在使用时需要注意这个。

原文地址:https://www.cnblogs.com/acefeng/p/12021276.html