JavaScript設計模式-單例模式

在軟件開發過程中,我們往往對於一些資源,只需要全局性的一個。比如說唯一的一個線程池,瀏覽器窗口中唯一的一個window對象等等。這時候,我們需要一類只能有一個實例,並提供一個訪問它的全局訪問點,這就是單例模式的概念。

實現單例模式最簡單的,就是設置一個標誌,又這個標誌來判斷是否已經創建了該類。

var singleton = function( name ){
    this.name = name;
    this.instance = null;
}

singleton.prototype.sayName = function(){
    console.log(this.name);
}
singleton.getInstance = function(name){
    if(!this.instance)
    {
        this.instance = new singleton(name);
    }
    return this.instance;
}

//測試
var ins1 = singleton.getInstance('liu');
var ins2 = singleton.getInstance('yang');
ins1 == ins2    //返回爲true;並且此時調ins2.sayName打印的是'liu'

這就是一個單例,但是這種實現方式是有缺點的,必須規定創建類用singleton.getInstance方法纔可以,否則這個類我們照樣也可以用new來創建,這時候這就不是一個單例的模式了。

爲了可以用new關鍵字來創建單例,跟普通實習的創建方式相同,我們可以改寫成下面這樣:

var singleton = (function( name ){
    var instance;
    var create = function(name){
        if(instance)
        {
            return instance;
        }
        this.name = name;
        return instance=this;
    }
    return create;
})();

var a = new singleton('liu');
var b = new singleton('yang');
a == b;    //返回true

實際創建的是create這個類,並且只會實例一次。

最後來寫一個通用的單例,比如我們有些時候想把一個對象作爲普通對象去使用,有時候又想作爲單例去使用,而且我一個單例的函數就可以生成很多種不同類型的單例,這時候可以將實現單例時共有的部分抽出來,而將一些個性作爲參數傳到函數裏面。比如下面這種方式:

function Poll(){
    this.name='線程池';
    return this;
}
function Global(){
    this.name = 'window對象';
    return this;
}
var single = function(fn){
    var instance;
    return function(){
        return instance || (instance=fn.apply(this, arguments))
    }
}
//創建線程池單例的函數
var pollInstance = single(Poll);

//創建Window對象單例的函數
var winInstance = single(Global);

上面兩個函數其實是相同的函數,不同的是傳的參數不同,同時這裏利用了閉包,即每次運行pollInstance之後的instance變量是不會從內存中消失的。
單例模式有很多應用,比如我們給某個DOM添加點擊事件,添加一次就可以了,這時候可以利用一個單例模式;或者我們做一個輪播圖,只需要整個div中有一個img元素,每次去換src就可以,這時候就可以把創建img元素加到div中的操作用單例模式來實現等等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章