单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
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!
网友评论