最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 面试之-javascript设计模式

    正文概述 掘金(WILL)   2021-03-27   394

    一, 参考文献: <<Javascipt 设计模式与开发实践>> -- 曾探

    二, 设计模式的目的

    • 设计模式是为了更好的代码重用性, 可读性,可靠性, 可维护性
    • 学会理解了设计模式, 就会发现生活中无处不在

    三, 设计模式分类

    • 创建型: 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
    • 结构型: 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    • 行为型: 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

    以下我们将学习常见的设计模式:

    四, 常见设计模式

    1. 单例模式

    • 定义: 保证一个类仅有一个实例, 并提供一个访问他的全局访问点
    • 比如有些对象我们只需要一个, 比如线程池, 全局缓存, 登录, 购物车等, 这种我们适合使用单例模式
        class SingleObj {
          login() {}
        }
        SingleObj.getInstance = (function() {
          let instance;
          return function() {
            if (!instance) {
              // 如果实例没有被创建, 则创建新的实例
              instance = new SingleObj();
            }
            return instance;
          };
        })();
        let a = SingleObj.getInstance();
        let b = SingleObj.getInstance();
        // console.log("a", a == b);
    
    • 应用场景:JQuery中的$、Vuex中的Store、Redux中的Store等

    2. 策略模式

    • 定义: 定义一系列的算法, 并把他们一个个封装起来, 并且使他们可以相互替换
        let strategy = {
          A: function(price) {
            return price * 2;
          },
          B: function(price) {
            return price * 2;
          },
          C: function(price) {
            return price * 2;
          }
        };
        function calc(price, type) {
          return strategy[type](price);
        }
        calc(100, "A");
    
    
    • 应用场景: 表单验证等

    3. 代理模式

    • 定义: 为一个对象提供一个代用品或占位符, 以便控制对他的访问
        // 案例: jack 通过代理对象送花给rose
        class Flower {}
        class Jack {
          constructor(target) {
            this.target = target;
          }
          sendFlower(target) {
            // jack送花 rose收到花
            const flower = new Flower(); // 创建花
            this.target.receiveFlower(flower); // 目标对象收到花
          }
        }
        // 目标对象
        class Rose {
          receiveFlower(flower) {
            console.log("收到花", flower);
          }
        }
        class Proxy {
          constructor() {
            this.target = new Rose(); // 目标对象为rose
          }
          sendFlower(flower) {
            // 代理对象送花
            this.receiveFlower(flower);
          }
          // 目标对象收到花
          receiveFlower(flower) {
            this.target.receiveFlower(flower);
          }
        }
    
        let proxyPerson = new Proxy(); // 代理对象
        let jack = new Jack(proxyPerson); // 杰克
        jack.sendFlower(proxyPerson); // 杰克送花
    
    • 应用场景: ES6 proxy, Vuex中对于getters访问、图片预加载等

    4. 迭代器模式

    • 定义: 按一个方法顺序访问一个聚合对象中的每一个元素, 而又无需暴露该对象的内部显示

    内部迭代器

    • 内部定义好迭代规则, 外部只需要调用一次
        const each = (args, fn) => {
          for (let i = 0; i < args.length; i++) {
            const value = fn(args[i], i, args);
            if (!value) break; // 跳出循环
          }
        };
        each([1, 2, 3], function(item, index) {
          console.log(item, index);
        });
    

    外部迭代器

    • 必须显示的请求迭代下一个元素。
        class Iterator {
          constructor(list) {
            this.list = list;
            this.index = 0;
          }
          next() {
            if (this.hasNext()) {
              return this.list[this.index++];
            }
            return null;
          }
          hasNext() {
            if (this.list.length === this.index) {
              return false;
            }
            return true;
          }
        }
        let ite = new Iterator([1, 2, 3, 4]);
        ite.next();
    
    • 应用场景: JS Iterator、JS Generator

    5. 工厂模式

    • 定义: 常见的实例化对象模式
       // 具体的对象
        class Product {
          constructor(name) {
            this.name = name;
          }
        }
        // 工厂类
        class Creator {
          create(name) {
            return new Product(name);
          }
        }
    
        let creators = new Creator();
        creators.create("jojo");
    
    • 应用场景:JQuery中的$、Vue.component异步组件、React.createElement等

    6. 发布订阅者模式

    • [欢迎查看本人的另外一篇文章- 发布订阅者模式解析] (juejin.cn/post/694117…)

    7. 装饰者模式

    • 定义: 在不改变对象本身的基础上, 在程序运行期间动态的添加方法
    • 简单版
        class Plane {
          fire() {
            console.log("开火");
          }
        }
        class Mixin {
          constructor(obj) {
            this.obj = obj;
          }
          attack() {
            this.obj.fire();
            console.log("开炮");
          }
        }
        let plane = new Plane();
        let mixin = new Mixin(plane);
        mixin.attack();
    
    • 利用AOP给函数动态添加功能
        Function.prototype.before = function(fn) {
          let self = this; // 保存原函数引用
          return function() {
            fn.apply(this, arguments); // 新函数执行
            return self.apply(this, arguments); // 原函数执行
          };
        };
        Function.prototype.after = function(fn) {
          let self = this;
          return function() {
            let ret = self.apply(this, arguments);
            fn.apply(this, arguments);
            return ret;
          };
        };
    
        function f1() {
          console.log(1);
        }
        let f = f1
          .before(function() {
            console.log(2);
          })
          .after(function() {
            console.log(3);
          });
        f();
    
    • 应用场景:ES7装饰器、Vuex中1.0版本混入Vue时,重写init方法、Vue中数组变异方法实现等

    8.适配器模式

    • 定义: 用来解决两个接口不兼容的问题, 由一个对象包裹不兼容的对象, 比如参数转换, 允许直接访问
        class Adapter {
          specify() {
            return "德国标准插头";
          }
        }
        class Target {
          constructor(target) {
            this.target = new Adapter();
          }
          requset() {
            let tips = this.target.specify();
            console.log(`${tips} - 转换器 - 中国标准插头`);
          }
        }
        let target1 = new Target();
        target1.requset();
    

    9. 中介者模式

    • 定义: 通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,
    • 当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
        var mediator = (function() {
          var colorSelect = document.getElementById("colorSelect");
          var memorySelect = document.getElementById("memorySelect");
          var numSelect = document.getElementById("numSelect");
          return {
            changed: function(obj) {
              switch (obj) {
                case colorSelect:
                  //TODO
                  break;
                case memorySelect:
                  //TODO
                  break;
                case numSelect:
                  //TODO
                  break;
              }
            }
          };
        })();
        colorSelect.onchange = function() {
          mediator.changed(this);
        };
        memorySelect.onchange = function() {
          mediator.changed(this);
        };
        numSelect.onchange = function() {
          mediator.changed(this);
        };
    

    10. 外观模式

    • 为一组复杂的子系统接口提供一个更高级的统一接口, 通过这个接口更容易访问子系统接口, 不符合开放封闭原则
        class A {
          eat() {}
        }
    
        class B {
          eat() {}
        }
        class C {
          eat() {
            const a = new A();
            const b = new B();
            a.eat();
            b.eat();
          }
        }
    
        // 跨浏览器事件监听
        function addEvent(el, type, fn) {
          if (window.addEventListener) {
            el.addEventListener(type, fn, false);
          } else if (window.attachEvent) {
            el.attachEvent('on' +type, fn);
          } else {
            el["on" + type] = fn;
          }
        }
    
    
    • 应用场景:JS事件不同浏览器兼容处理、同一方法可以传入不同参数兼容处理等

    今天真是让人头凸且充实的一天啊~~~


    起源地下载网 » 面试之-javascript设计模式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元