09.08 「講得明白的設計模式」JS單例模式-計劃生育模式

單例模式

單例模式也稱作為單子模式,更多的也叫做單體模式。為軟件設計中較為簡單但是最為常用的一種設計模式。通俗的說,就是在程序裡搞計劃生育,某種特定的對象就是你的娃,只能生1個,別人要想讓你在生個娃,你就把你的這個娃給他看。

「講得明白的設計模式」JS單例模式-計劃生育模式

到了咋們這個年代改收單身稅了(>_

對於前端JavaScript來說,我們可能平時會寫能實例化彈框對象的類。但你希望的是如果頁面上已經有彈框了,那麼實例化出來的依然是老的那個彈框對象。只有沒有任何彈框的情況下,才實例化1個新的彈框對象。

「講得明白的設計模式」JS單例模式-計劃生育模式

反正只能有1個彈框

下面是維基百科對單例模式的介紹,可以跳過,反正也看不懂:

在應用單例模式時,生成單例的類必須保證只有一個實例的存在,很多時候整個系統只需要擁有一個全局對象,才有利於協調系統整體的行為。比如在整個系統的配置文件中,配置數據有一個單例對象進行統一讀取和修改,其他對象需要配置數據的時候也統一通過該單例對象來獲取配置數據,這樣就可以簡化複雜環境下的配置管理。

「講得明白的設計模式」JS單例模式-計劃生育模式

好,現在,我們來看看單例模式的思路是:一個類能返回一個對象的引用(並且永遠是同一個)和一個獲得該實例的方法(靜態方法,通常使用 getInstance 名稱)。那麼當我們調用這個方法時,如果類持有的引用不為空就返回該引用,否者就創建該類的實例,並且將實例引用賦值給該類保持的那個引用再返回。同時將該類的構造函數定義為私有方法,避免其他函數使用該構造函數來實例化對象,只通過該類的靜態方法來得到該類的唯一實例。

對於JavaScript來說,循規蹈矩的方式顯得過於笨重,在不同的場景以不同的方式實現單體模式正是JavaScript的優勢。

實現1: 最簡單的對象字面量

var singleton = {
attr : 1,
method : function(){ return this.attr; }
}
var t1 = singleton ;
var t2 = singleton ;

那麼很顯然的, t1 === t2 。

十分簡單,並且非常使用,不足之處在於沒有什麼封裝性,所有的屬性方法都是暴露的。對於一些需要使用私有變量的情況就顯得心有餘而力不足了。當然在對於 this 的問題上也是有一定弊端的。

實現2:構造函數內部判斷

其實和最初的JS實現有點類似,不過是將對是否已經存在該類的實例的判斷放入構造函數內部。

function Construct(){
// 確保只有單例
if( Construct.unique !== undefined ){
return Construct.unique;
}
// 其他代碼
this.name = "NYF";
this.age="24";
Construct.unique = this;
}
var t1 = new Construct() ;
var t2 = new Construct() ;

那麼也有的, t1 === t2 。

也是非常簡單,無非就是提出一個屬性來做判斷,但是該方式也沒有安全性,一旦我在外部修改了Construct的unique屬性,那麼單例模式也就被破壞了。

實現3 : 閉包方式

對於大著 靈活 牌子的JS來說,任何問題都能找到 n 種答案,只不過讓我自己去掂量孰優孰劣而已,下面就簡單的舉幾個使用閉包實現單例模式的方法,無非也就是將創建了的單例緩存而已。

var single = (function(){
var unique;
function Construct(){
// ... 生成單例的構造函數的代碼
}
unique = new Constuct();
return unique;
})();

只要 每次講 var t1 = single; var t2 = single;即可。 與對象字面量方式類似。不過相對而言更安全一點,當然也不是絕對安全。

如果希望會用調用 single() 方式來使用,那麼也只需要將內部的 return 改為

 return function(){
return unique;
}

以上方式也可以使用 new 的方式來進行(形式主義的趕腳)。當然這邊只是給了閉包的一種例子而已,也可以在 Construct 中判斷單例是否存在 等等。 各種方式在各個不同情況做好選著即可。

總結

總的來說,單例模式相對而言是各大模式中較為簡單的,但是單例模式也是較為常用並且很有用的模式。在JS中尤為突出(每個對象字面量都可以看做是一個單例麼~)。

記住,是否嚴格的只需要一個實例對象的類(雖然JS沒有類的概念),那麼就要考慮使用單例模式。

使用數據緩存來存儲該單例,用作判斷單例是否已經生成,是單例模式主要的實現思路。


分享到:


相關文章: