单例模式:限制类只能有一个实例化对象。

模式特点:

  • 类只有一个实例
  • 全局可访问
  • 推迟初始化(与静态类,对象的区别)
  • 主动实例化

实现方法:
创建一个类,这个类包含一个方法。在没有对象的情况下,这个方法会创建一个新的实例对象。如果对象存在,则只返回对象的引用地址。

应用场景:

  • 登录弹窗
  • 购物车
  • 命名空间
  • 引入第三方库(多次引用只会使用一个库引用,如jQuery)
  • 全局态管理store-Vuex

优缺点:

  • 优点:适用于单一对象,只生成一个对象实例,避免频繁创建和销毁实例,减少内存占用
  • 缺点:不适用动态扩展对象,或需创建多个相似对象的场景

“简单版”单例模式:

   let Signleton = function(name){
      this.name = name
      this.instance = null
    }

    Signleton.prototype.getName = function(){
      console.log(this.name);
    }

    Signleton.getInstance = function(name){
      if(this.instance){
        return this.instance
      }
      return this.instance = new Signleton(name)
    }

    let Winner = Signleton.getInstance('Winner')
    let Loser = Signleton.getInstance('Loser')

    console.log(Winner === Loser);
    console.log(Winner.getName()); // Winner
    console.log(Loser.getName()); //Loser

"透明版"单例模式
统一使用 new在进行实例化,创建实例功能和管理实例功能分离,使其符合‘单一职责原则’

    let createSignleton = (function(){
      let instance;
      return function(name){
        if(instance){
          return instance
        }
        this.name = name
        return instance = this
      }
    })()

    createSignleton.prototype.getName = function(){
      console.log(this.name);
    }

    let Winner = new createSignleton('Winner')
    let Loser = new createSignleton('Loser')

    console.log(Winner === Loser);
    console.log(Winner.getName()); // Winner
    console.log(Loser.getName()); //Loser

“代理版”单例模式
通过代理的模式,意图将创建单例,管理单例拆分,实现更小的粒度划分,符合‘单一职责原则’

    let ProxyCreateSignleton = (function(){
      let instance;
      return function(name){
        // 代理函数只做管理单例
        if(instance){
          return instance
        }
        return instance = new Signleton(name)
      }
    })()

    // 独立的Signleton类,处理对象实例
    let Signleton = function(name){
      this.name = name
    }

    Signleton.prototype.getName = function(){
      console.log(this.name);
    }

    let Winner = new ProxyCreateSignleton('Winner')
    let Loser = new ProxyCreateSignleton('Loser')

    console.log(Winner === Loser);
    console.log(Winner.getName()); // Winner
    console.log(Loser.getName()); //Loser

“惰性”单例模式
需要时才创建实例对象,按需加载。

需求:页面弹窗提示。多次调用,都只有一个弹窗对象,内部html不同

    let getSignleton = function(fn){
      var result;
       return function(){
         return result || (result = fn.apply(this, arguments))
       }
    }

    let createAlterMessage = function(html){
      var div = document.createElement('div')
      div.innerHTML = html;
      div.style.display = 'none'
      document.body.appendChild(div)
      return div
    }

    let createSignletonAlterMessage = getSignleton(createAlterMessage)
    document.getElementById('btn').addEventListener('click', function(){
      let alterMessage = createAlterMessage('这是唯一弹窗')
      alterMessage.style.display = 'block'
    })

参考文章:
https://segmentfault.com/a/1190000019532633
https://www.jianshu.com/p/7fa6ea107eff
https://juejin.cn/post/6909737165157203982#comment

Logo

前往低代码交流专区

更多推荐