美文网首页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