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

  • 相关阅读:
    Chrome浏览器M53更新后超链接的dispatchEvent(evt)方法无法触发文件下载
    用es5实现模板字符串
    JS求数组最大值常用方法
    js生成随机数
    常用MouseEvent鼠标事件对象&KeyboardEvent键盘事件对象&常用键盘码
    原生js重写each方法
    indexdb开cai发keng实zhi践lu
    substring和substr的区别和使用
    前端常见面试题总结part2
    前端常见面试题总结1
  • 原文地址:https://www.cnblogs.com/acefeng/p/12021276.html
Copyright © 2020-2023  润新知