標籤:javascript模式 singleton 單例
singleton模式限制了類的執行個體化次數只能有一次。singleton模式,該執行個體不存在的情況下,可以通過一個方法建立一個類來實現建立類的新執行個體;如果執行個體已經存在,它會簡單的返回對象的引用。Singleton不同於靜態類,它可以延遲執行個體化。
1.對象字面量實現
在javascript中實現單例模式有很多方式,其中最簡單的就是對象字面量。
var Singleton={ name:"vuturn", showName:function(){ console.log(this.name); } }
當然也可以擴充該對象,可以添加私人成員和方法,使用閉包在其內部封裝變數和方法。通過返回一個對象,暴露公有的方法和變數。
2.利用閉包實現
var mySingleton=(function(){ var instance; function init(){ function privateMethod(){ console.log("This is private"); } var privateVariable="This is privart too!"; return { publicMethod:function(){ console.log("This is public!"); }, publicProperty:"This is public too!" } } return { getInstance: function () { if(!instance){ instance=init(); } return instance; } } })();
3.使用new 操作符
我們要實現以下效果:
var uni=new Universe(), uni2=new Universe();uni==uni2;
uni對象在第一次調用建構函式時建立,在第二次(或者更多次)時,直接返回同一個uni對象。這就是為什麼uni===uni2,因為指向同一個對象的引用。
那麼如何在javascript中實現這種模式呢?
需要Universe對象緩衝this對象,以便第二次調用的時候 能夠建立並返回同一個對象。有多種方式實現這一目標。
(1)可以使用全域變數來儲存該執行個體。但是並不推薦這種做法,因為全域變數容易被覆蓋。
(2)可以在建構函式的靜態屬性中緩衝該執行個體。這種簡潔做法的唯一缺點在於靜態屬性是公開訪問的屬性,外部代碼可以修改。
(3)可以將該執行個體封裝在閉包中。這樣可以保證執行個體的私人性並且保證執行個體不會被建構函式之外的代碼修改。
這裡展示第二和第三種實現方式:
靜態屬性中的執行個體
function Universe(){ if(typeof Universe.instance ==="object"){ return Universe.instance; } this.start_time=0; Universe.instance=this; return this; } var uni=new Universe(); var uni2=new Universe(); console.log( uni===uni2 );
閉包中的執行個體
function Universe(){ var instance=this; this.start_time=0; Universe= function () { return instance; } } var uni=new Universe(); var uni2=new Universe(); console.log( uni===uni2 );
上面的代碼在第一次調用時,返回this指標,這時的建構函式已經被重寫,以後再調用時,直接返回instance。這種模式的缺點在於重寫了建構函式,會丟失所有在初始定義和重定義時刻之間添加到它裡面的屬性。在這裡的特定的情況下,任何添加到Universe的原型中的對象都不會存在指向友原始實現所建立的活動連結。
看看下面的測試:
Universe.prototype.nothing=true; var uni=new Universe(); Universe,prototype.everything=true; var uni2=new Universe(); uni.nothing; //true uni2.nothing; //true uni.everything; //undefined uni2.everything; //undefined uni.constructor.name; //Universe uni.constructor===Universe; //false
之所以uni.constructor不再與Universe()建構函式相同,是因為uni.constructor仍然指向原始的建構函式。
如果需要原型和建構函式指標按照預期的那樣運行,那麼可以通過如下的方式實現:
function Universe(){ var instance; Universe= function () { return instance; } //重寫原型 Universe.prototype=this; instance=new Universe(); instance.constructor=Universe; instance.start_time=0; return instance; } Universe.prototype.nothing=true; var uni=new Universe(); Universe.prototype.everything=true; var uni2=new Universe(); console.log(uni===uni2); console.log(uni); console.log(uni2); console.log(uni.constructor);
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
javascript設計模式之單例(singleton)模式