VOOZH about

URL: https://read01.com/5Jnem.html

⇱ javaScript幾種設計模式之一——單體模式 - 壹讀


Sunday, Apr 12, 2026

javaScript幾種設計模式之一——單體模式

2015/06/08 來源:CSDN博客

javaScript是一種弱類型、動態的、基於原型的語言,這種語言特性使得它非常容易、

甚至是普通的方式實現其中的一些模式。

單體模式的思想在於保證一個特定類僅有一個實例。這就意味著當您第二次使用同一個

類創建新對象的時候,應該得到與第一次所創建對象完全相同對象。

在javaScript中沒有類,只有對象。當您創建一個新對象時,實際上沒有其他對象與其

類似,因此新對象已經是單體了。使用對象字面量創建一個簡單的對象也是一個單體的

例子。

var obj ={

myprop:’my value』

};

在javaScript中,對象之間永遠不會完全相等,除非他們是同一個對象,因此即使創建

一個具有完全相同成員的同類對象,它也不會與第一個對象完全相同。

var obj2 = {

myprop:’mu value』

};

obj === obj2 //false

obj == obj2 //false

因此,可以認為每次在使用對象字面量創建對象的時候,實際上就正在創建一個單體,

並且並不涉及任何特殊語法。

javaScript中並沒有類,因此對單體咬文嚼字的定義嚴格說來並沒有意義。但是

javaScript中具有new語法可使用構造函數來創建對象,而且有時可能需要使用這種語法

的單體實現。這種思想在於當使用一個構造函數以new操作符來創建多個對象時,應該僅

獲得指向完全相同的對象的新指針。

下面的代碼顯示了其預期行為

var uni = new Universe;

var uni2 = new Universe;

uni === uni2; //true

在上面的例子中,uni對象僅在第一次調用構造函數時被創建。在第二次及以後的創建時

將會返回同一個uni對象。這就是為什麼uni===uni2,因為它們本質上是指向同一個對象

的兩個引用。那麼如何在javaScript中實現這種模式呢?

需要Universe構造函數緩存該對象實例this,以便當第二次調用該構造函數時能夠創建並

返回同一個對象。有多種選擇可以實現這一目標:

1.可以使用全局變量來存儲該實例,但是並不推薦使用這種方法,因為在一般原則下,

全局變量有部分缺點。此外,任何人都能覆蓋該全局變量。

  1. 可以在構造函數的靜態屬性中緩存該實例,javaScript中的函數也是對象,因此它們

也可以有屬性。可以使用類似Universe.instance的屬性並將實例緩存在該屬性重工,這

是一種很好的實現方法,這種解決方案唯一的缺點在於instance屬性是公開可訪問的屬

性,在外部代碼中可能會修改該屬性,以至於會丟失了該實例。

如例子:

function Universe{

//判斷是否有實例

if(typeof Universe.instance === 『object』){

return Universe.instance;

}

//正常進行

this.start_time = 0;

this.bang = 「Big」;

//緩存

Universe.instance = this;

}

//

var uni = new Universe;

var uni2 = new Universe;

uni === uni2; //true

這種方法是一個非常直接的解決方法,其唯一的缺點在於其instance屬性是公開的,雖

然其他代碼不太可能會無意中修改該屬性,但是仍然存在這種可能性。

3.可以將該實例包裝在閉包中。這樣可以保證該實例的私有屬性並且保證該實例不會被

構造函數之外的代碼所修改,缺點就是帶來了額外的閉包開銷。

如下面例子:

function Universe{

//緩存實例

var instance = this;

//正常進行

this.start_time=0;

this.bang = 「big」;

//重寫該構造函數

Universe = function{

return instance;

};

}

var uni = new Universe;

var uni2 = new Universe;

uni === uni2; //true

當第一次調用原始構造函數時,它像往常一樣返回this,然後,在第二次、第三次調用

時,將執行重寫構造函數。該重寫構造函數通過閉包訪問了私有instance 變量,並且僅

簡單返回了該instance.在重寫構造函數會丟失所有在初始定義和重定義時刻之間添加到

它裡面的屬性。在這列的特定情況下,任何添加到universe的原型中對象都不會存在指

向由原始實現所創建實例的活動連結。

另外一種方法是將構造函數和實例包裝在即時函數中。在第一次調用構造函數時,它會

創建一個對象,並且似的私有instance指向該對象,從第二次調用之後,該構造函數僅

返回該私有變量,通過這個新的實現方式,前面所有代碼片段的測試也都會按照預期運

行。

var Universe;

(function {

var instance;

Universe = function Unvierse{

if(instance){

return instance;

}

instance = this;

//所有功能

this.start_time = 0;

this.bang = 「Big」;

};

});

您可能感興趣
免責聲明:本文內容來源于CSDN博客,文章觀點不代表壹讀立場,如若侵犯到您的權益,或涉不實謠言,敬請向我們提出檢舉
最新文章 / 服務條款 / 私隱保護 / DMCA / 聯絡我們

壹讀/READ01.COM