保证一个类仅生成一个实例,并能够全局访问。javascript
单列模式应用很是普遍,有些场景下某些对象只须要一个,好比浏览器中的window对象,全局缓存对象等。在实际开发过程当中应用也比较多,好比点击一个按钮产生一个登录框,不管点击多少次都应该只在第一次产生这个登陆框,而在后面点击N次也只能是复用这个登录框,而非从新建立,这样的场景就可使用单列模式来建立这个登录框。html
//简单版单列模式
const Singleton = function (name) {
this.name = name
//这个instance来保存生成的实例
this.instance = null
}
Singleton.prototype.getName = function () {
return this.name
}
//静态方法
Singleton.getInstance = function (name) {
if (!this.instance){
this.instance = new Singleton(name)
}
return this.instance
}
const A = Singleton.getInstance('A')
const B = Singleton.getInstance('B')
console.log(A === B); //true
console.log(A.getName()); //A
console.log(B.getName()); //A
复制代码
要实现起来并不复杂,无非就是使用一个私有变量去保存已生成的实例,在下新建时判断是否存在这个实例,若存在直接返回,而不建立就OK了。java
透明板也就要用new Constructor的形式建立对象,使用单例的类就像使用普通的类同样。 下面咱们使用闭包的形式来写一个单列类,并使用闭包的局部变量来保存已生成的实例。浏览器
//透明板单列模式
const Singleton = (function () {
let instance = null
//实现一个简单的类
function createDiv(html){
if (instance){
return instance
}
this.html = html
return instance = this
}
createDiv.prototype.init = function () {
let div = document.createElement('div')
div.innerHTML = this.html
document.body.append(div)
}
return createDiv
})()
const A = new Singleton('A')
const B = new Singleton('B')
console.log(A === B); //true
复制代码
代理版本要实现的目标是将定义类的代码和管理单例的代码分开,实现更小粒度的划分,遵循单一职责原则缓存
const Singleton = function (name){
this.name = name
}
const proxySingleton = (function () {
let instance = null
return function (name) {
if (!instance){
instance = new Singleton(name)
}
return instance
}
})()
复制代码
前面写的例子都是基于'类'的单例模式,其目的在与建立一个惟一的由'类'生成的对象(这里的'类'指的是伪类,也就是咱们把javascript中的构造函数当作其余传统语言中的类来进行理解,而其实javascript中是不存在类的的概念,全部对象都是构造函数基于原型克隆出来的,快扯到面向对象去了,这里就很少说了)
理解惰性单例有以下两点
一、而如今要理解的 "惰性单例"的概念,咱们的思想再也不局限于去实现一个全局惟一的由伪类生成的对象,咱们维持的惟一单例多是一个div,多是一个列表,也天然多是一个对象。
二、另外要理解的是 '惰性'二字,也即 咱们维持的单例在不须要的状况下是不会产生的,只有在须要的状况才会生成,其实这一点在第二节简单的单例模式里面就已经实现了,只有调用Singleton.getInstance才会生成,而且生成后会一直存在,等待复用
一个例子:
好比咱们须要一个登录框,而在页面上点击登录就会弹出这个登录框,不管屡次点击生成的都应该是同一个DOM节点,而这个DOM节点只在第一次调用生成,后面点击登录只会复用这个DOM节点。这里咱们维持的惟一单例应该是登录框的DOM节点,而且是惰性生成的,即永不点击登陆,就永远不会生成该DOM节点。
下面给出惰性单例的通用代码bash
//惰性单例通用代码
const getSingle = function (fn){
let instance = null;
return function (){
return instance || (instance = fn.call(this, arguments))
}
}
复制代码
要实现上面维持登陆框单例的例子, 这里说一下思路, fn的功能是产生登陆框,并返回登陆框的DOM,代码以下闭包
const createLoginLayer = function(){
let div = document.createElement( 'div' );
div.innerHTML = '我是登陆浮窗';
div.style.display = 'none';
document.body.appendChild( div );
return div;
};
let createSingleLoginLayer = getSingle( createLoginLayer );
document.getElementById( 'loginBtn' ).onclick = function(){
let loginLayer = createSingleLoginLayer();
loginLayer.style.display = 'block';
};
复制代码
单例模式在开发过程当中应用很普遍,特别是惰性单例,因此也是咱们必需要掌握的点。而后要再啰嗦几句的就是关于,单一职责原则,开放封闭原则,最少知识原则等等面向对象的概念,不管是上面提到的仍是没提到的,咱们都须要有必定的了解,熟悉这些原则并应用于实际对于代码质量的提高确定是巨大的。app