美文网首页js设计模式
js常用算法1---单例模式

js常用算法1---单例模式

作者: 青色琉璃 | 来源:发表于2020-11-09 10:39 被阅读0次

    单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
    1,简单实现

    var Singleton = function (name) {
        this.name = name
    }
    Singleton.instance = null
    Singleton.prototype.getName = function () {
        console.log(this.name)
    }
    Singleton.getInstance = function (name) {
        if (!this.instance) {
            this.instance = new Singleton(name)
        }
        return this.instance
    
    }
    var a = Singleton.getInstance('a')
    var b = Singleton.getInstance('b')
    console.log(a === b)
    
    或者:
    
    var Singleton = function (name) {
      this.name = name
    }
    Singleton.prototype.getName = function () {
      console.log(this.name)
    }
    Singleton.getInstance = (function () {
      var instance = null
      return function (name) {
        if (!instance) {
          instance = new Singleton(name)
        }
        return instance
      }
    })()
    
    //所谓单例模式,就是只有一个对象实例
    var a = Singleton.getInstance('a')
    var b = Singleton.getInstance('b')
    console.log(a === b)
    

    在这段代码中,我们需要通过Singleton.getInstance来获取Singleton的实例,使用者必须知道Singleton类是一个单例类,这增加了代码的“不透明性”,通过Singleton.getInstance获取对象的方式也与一般的new方法获取不同。这段单例模式代码的意义不大

    2,透明的单例模式

     //透明的单例模式
    var CreateDiv = (function () {
      var instance
      var CreateDiv = function (html) {
        if (instance) {
          return instance
        }
        this.html = html
        this.init()
        return instance = this
      }
      CreateDiv.prototype.init = function () {
        //node里面没有document,会报错
        var div = document.createElement('div')
        div.innerHTML = this.html
        document.body.appendChild(div)
      }
      return CreateDiv
    })()
    var a = new CreateDiv('a')
    var a = new CreateDiv('b')
    

    现在我们实现了一个透明的单例类的编写,但仍有一些问题
    CreateDiv类中实际上有两个功能:创建对象和执行初始化init方法、保证只有一个对象。不符合单一职责原则。
    当我们需要取消单例,变成一个正常的构造函数时,修改代码会带来一些不必要的麻烦

    3,透明单例改-代理模式

    // 用代理实现代理模式
    var CreateDiv = function (html) {
        this.html = html
        this.init()
    }
    CreateDiv.prototype.init = function () {
        var div = document.createElement('div')
        CreateDiv.innerHtml = this.html
        document.body.appendChild(div)
    }
    
    var ProxySingletonCreateDiv = (function () {
        var instance
        return function (html) {
            if (!instance) {
                instance = new CreateDiv(html)
            }
            return instance
        }
    })()
    var a = ProxySingletonCreateDiv('a')
    var b = ProxySingletonCreateDiv('b')
    console.log(a === b)
    

    现在,负责管理单例的的逻辑在ProxySingletonCreateDiv中实现,CreateDiv就是一个普通的类,美滋滋

    4,惰性单例
    惰性单例指的是在需要的时候才创建对象实例。惰性单例是单例模式的重点。
    在javaScript中,基于类的单例模式并不适用,需要转变思路
    4.1,弹框功能

    var loginLayer = (function () {
        var div = document.createElement('div')
        div.innerHTML = '我要登录,不给就送'
        div.style.display = 'none'
        document.body.appendChild(div)
        return div
    })()
    document.getElementById('loginBtn').onclick = function () {
        loginLayer.style.display = 'block'
    }
    

    缺点:loginLayer在页面进来之后就直接执行了,如果用户不需要这个弹框,很浪费

    4.2,弹框功能节约版

    var createLoginLayer = function () {
         var div = document.createElement('div')
         div.innerHTML = '我要登录,不给就送'
         div.style.display = 'none'
         document.body.appendChild(div)
         return div
     }
     document.getElementById('loginBtn').onclick = function () {
         var loginLayer = createLoginLayer()
         loginLayer.style.display = 'block'
     }
    

    虽然节约了,但是每次点击的时候都会创建新的div,失去了单例的效果

    4.3,弹框功能单例版

    var createLoginLayer = (function () {
        var div
        return function () {
            if (!div) {
                div = document.createElement('div')
                div.innerHTML = '我要登录,不给就送'
                div.style.display = 'none'
                document.body.appendChild(div)
            }
            return div
        }
    })()
    document.getElementById('loginBtn').onclick = function () {
        var loginLayer = createLoginLayer()
        loginLayer.style.display = 'block'
    }
    

    确实实现了单例的功能,但是弹框的创建和管理(if(!div) return div这段控制返回的代码)都在createLoginLayer中实现,违反了单一职责原则

    4.4,弹框功能OK版

     var getSingle = function (fn) {
        var result
        return function () {
            return result || (result = fn.apply(this, arguments))
        }
    }
    var createLoginLayer = function () {
        var div = document.createElement('div')
        div.innerHTML = '我要登录,不给就送'
        div.style.display = 'none'
        document.body.appendChild(div)
        return div
    }
    var createSingleLoginLayer = getSingle(createLoginLayer)
    document.getElementById('loginBtn').onclick = function () {
        var loginLayer = createSingleLoginLayer()
        loginLayer.style.display = 'block'
    }
    

    good!

    相关文章

      网友评论

        本文标题:js常用算法1---单例模式

        本文链接:https://www.haomeiwen.com/subject/msklbktx.html