天天看點

js設計模式之單例模式

js設計模式之單例模式

1、定義

保證一個類僅生成一個執行個體,并可以全局通路。

2、應用範圍

單列模式應用非常廣泛,有些場景下某些對象隻需要一個,比如浏覽器中的window對象,全局緩存對象等。在實際開發過程中應用也比較多,比如點選一個按鈕産生一個登陸框,無論點選多少次都應該隻在第一次産生這個登入框,而在後面點選N次也隻能是複用這個登陸框,而非重新建立,這樣的場景就可以使用單列模式來建立這個登陸框。

3、實作一個簡單的單例模式

//簡單版單列模式

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了。

4、透明版

透明闆也就要用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')

5、代理版

代理版本要實作的目标是将定義類的代碼和管理單例的代碼分開,實作更小粒度的劃分,遵循單一職責原則

const Singleton = function (name){

this.name = name           

const proxySingleton = (function () {

let instance = null
return function (name) {
    if (!instance){
        instance = new Singleton(name)
    }
    return instance
}           

6、惰性單例

前面寫的例子都是基于'類'的單例模式,其目的在與建立一個唯一的由'類'生成的對象(這裡的'類'指的是僞類,也就是我們把javascript中的構造函數當做其他傳統語言中的類來進行了解,而其實javascript中是不存在類的的概念,所有對象都是構造函數基于原型克隆出來的,快扯到面向對象去了,這裡就不多說了)

了解惰性單例有如下兩點

1、而現在要了解的 "惰性單例"的概念,我們的思想不再局限于去實作一個全局唯一的由僞類生成的對象,我們維持的唯一單例可能是一個div,可能是一個清單,也自然可能是一個對象。

2、另外要了解的是 '惰性'二字,也即 我們維持的單例在不需要的情況下是不會産生的,隻有在需要的情況才會生成,其實這一點在第二節簡單的單例模式裡面就已經實作了,隻有調用Singleton.getInstance才會生成,并且生成後會一直存在,等待複用

一個例子:

比如我們需要一個登陸框,而在頁面上點選登陸就會彈出這個登陸框,無論多次點選生成的都應該是同一個DOM節點,而這個DOM節點隻在第一次調用生成,後面點選登陸隻會複用這個DOM節點。這裡我們維持的唯一單例應該是登陸框的DOM節點,并且是惰性生成的,即永不點選登入,就永遠不會生成該DOM節點。

下面給出惰性單例的通用代碼

//惰性單例通用代碼

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';           

7、小結

單例模式在開發過程中應用很廣泛,特别是惰性單例,是以也是我們必須要掌握的點。然後要再啰嗦幾句的就是關于,單一職責原則,開放封閉原則,最少知識原則等等面向對象的概念,無論是上面提到的還是沒提到的,我們都需要有一定的了解,熟悉這些原則并應用于實際對于代碼品質的提升肯定是巨大的。

原文位址

https://www.cnblogs.com/chenlei987/p/11356439.html

繼續閱讀