javascript的设计模式

设计模式的目的

设计模式是为了更好的代码重用性, 可读性,可靠性, 可维护性

学会理解了设计模式, 就会发现生活中无处不在

  设计模式分类

创建型: 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式

结构型: 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型: 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

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

四, 常见设计模式

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设计模式** ## **设计模式简介** 设计模式代表了最佳的实践,通常被有经验的面...
    你别太自信阅读 200评论 0 0
  • javascript设计模式 从声明上,函数也是变量 在javascript中,在全局作用域中定义变量得非常小心,...
    loser_b45d阅读 283评论 0 2
  • 转载自:https://www.cnblogs.com/chenxygx/p/5754101.html Javas...
    persistlu阅读 306评论 0 0
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,592评论 28 53
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,223评论 4 8