保證一個類僅生成一個實例,並能夠全局訪問。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