从JavaScript学习设计模式-02单例模式

保证一个类仅有一个实例,并且提供一个访问它的全局访问点

单例模式的思路是:一个类能返回一个对象的引用(并且永远是同一个)和一个获得该实例的方法(静态方法,通常使用 getInstance 名称)。那么当我们调用这个方法时,如果类持有的引用不为空就返回该引用,否者就创建该类的实例,并且将实例引用赋值给该类保持的那个引用再返回。同时将该类的构造函数定义为私有方法,避免其他函数使用该构造函数来实例化对象,只通过该类的静态方法来得到该类的唯一实例。

应用场景

日常开发中,经常制作弹窗的时候我们需要一个半透明的遮罩层,为了减少不必要的dom操作,我们正确的思路应该是,判断有没有生成过这个 model div 如果已经生成了就不必再次生成。

实现步骤

步骤1 写一个生成 model div的方法

   <style> .modal { position: fixed; left: 0; top: 0; width: 100%; height: 100%; opacity: .5; background: #000; z-index: 99; } </style>
  
 <script> function createModal () { const div = document.createElement('div'); div.className = 'modal'; document.body.appendChild(div); } createModal() createModal() // 调用两次 将会产生两个模态框 </script>  

复制代码

调用两次 createModal 方法将会产生在body上追加两个div 很显然不是我们需要的结果,我们需要增加一个变量判断是否已经调用过

根据单例模式的定义来实现

  1. 保证一个类仅有一个实例 new createModal()
  2. 并且提供一个访问它的全局访问点 createModal.getInstance 方法访问
  function createModal () {
    const div = document.createElement('div');
    div.className = 'modal';
    document.body.appendChild(div);
  }

  createModal.getInstance = function () {
    if (this.instace) {
      return this.instace;
    } else {
      this.instace = new createModal(); 
      return this.instace;
    }
  };
  const a = createModal.getInstance()
  const b = createModal.getInstance() // 调用两次 实例一次
  console.log(a === b)  // true
复制代码

此段代码就根据单例模式的定义来用js实现了一个单例模式,调用多次也只会实例一个 createModal ,生成一个模态框

惰性单例

由于js的特性,可用闭包的形式保护一个私有变量,让他来作为判断值,并且惰性函数代表:在需要的时候才创建对象实例,而非在页面加载时就创建

  const createModal = (function(){
    let div;
    return function(){
      if(!div){
        div = document.createElement('div');
        div.className = 'modal';
        document.body.appendChild(div);
      }
    }
  })();
  createModal()
  createModal() // 调用两次 div 生成一次

复制代码

通过闭包,保护了 div 变量,在调用时候判断

通用模式

通过上面代码我们发现如果需要新建另外一个div,只能复制代码,是否能想办法把 return 里生成div 的方法分离出来呢。

  1. 创建一个 getSingle 方法 result 为判断变量
  2. 创建一个 createModal 的方法为具体执行代码,并且返回一个bool值给 getSingle 中的 result 进行判断
  const getSingle = function (fn) {
    let result;
    return function () {
      return result || (result = fn.apply(this, arguments));
    }
  };
  const createModal = function () {
    const div = document.createElement('div');
    div.className = 'modal';
    document.body.appendChild(div);
    return div
  }
  const createSingleDiv = getSingle(createModal)
  const a = createSingleDiv()
  const b = createSingleDiv()
  console.log(a === b)  // true
复制代码

这样就创建了一个 创建惰性单例的通用模式了

总结

单例模式在实际开发中应用很多,特别是在框架设计,合理利用可以提高性能。

    原文作者:算法小白
    原文地址: https://juejin.im/post/5b74cf5ae51d4560f178cff2
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞