zoukankan      html  css  js  c++  java
  • 设计模式尝试(策略模式、代理模式、发布订阅者模式、职责链模式)---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元的金额进行处理。所以这个本身是存在浪费的,所以在使用时需要注意这个。

  • 相关阅读:
    CodeForces 706C Hard problem
    CodeForces 706A Beru-taxi
    CodeForces 706B Interesting drink
    CodeForces 706E Working routine
    CodeForces 706D Vasiliy's Multiset
    CodeForces 703B Mishka and trip
    CodeForces 703C Chris and Road
    POJ 1835 宇航员
    HDU 4907 Task schedule
    HDU 4911 Inversion
  • 原文地址:https://www.cnblogs.com/acefeng/p/12021276.html
Copyright © 2011-2022 走看看