摘要:原文單例模式被熟知是因為它把一個類的實例化限制在只有一個對象。這在中也是可以實現的。單例和靜態對象都很有用,但是不能過度使用。實踐中,當我們在整個系統中只需要一個對象與其他對象通信的時候,單例模式是非常有用的。
原文:The Single Pattern
單例模式被熟知是因為它把一個類的實例化限制在只有一個對象。傳統的實現方式是:創建一個類,這個類里面有一個方法在對象不存在的時候創造一個實例,存在的時候,只需要返回這個對象的引用即可。
單例和靜態類(或者對象)是有區別的,因為我們可以延遲他們的初始化。因為他們需要一些在初始化的時候不能獲得的信息。他們沒有提供一種方式讓不知道他們之前引用的代碼去獲取他們。這是因為由單例返回的既不是對象也不是類,而是一種結構。想想大括號形成的不是真正的閉包,函數作用于提供的閉包才是真正的閉包。
Javascript中,單例作為共享資源的命名空間,它隔離了實現的代碼和全局變量,為了能夠讓函數有唯一的一個入口。
我們可以通過下面的方法實現單例:
var mySingleton=(function(){ //存儲單例引用的實例 var instance; function init(){ //單例 //私有方法和屬性 function privateMethod(){ console.log("I am private"); } var privateVariable="Im alse private"; var privateRandomNumber=Math.random(); return { //公有方法和屬性 publicMethod:function(){ console.log("The public can see me!"); }, publicProperty:"I am also public", getRandomNumber:function(){ return privateRandomNumber; } }; } return { //如果存在獲取單例實例的引用 //不存在,創建實例 getInstance:function(){ if(!instance){ instance=init(); } return instance; } }; })(); var myBadSingleton=(function(){ //指向單例的引用 var instance; function init(){ //單例 var privateRandomNumber=Math.random(); return { getRandomNumber:function(){ return privateRandomNumber; } } } return { //無論什么時候都創建一個單例實例 getInstance:function(){ instance=init(); return instance; } }; })(); //使用: var singleA=mySingleton.getInstance(); var singleB=mySingleton.getInstance(); console.log(singA.getRandomNumber()===singleB.getRandomNumber()); //true var badSingleA=myBadSingleton.getInstance(); var badSingleB=myBadSingleton.getInstance(); console.log(badSingleA.getRandomNumber()!==badSingleB.getRandomNumber());//true //注意:因為我們使用的是隨機數 //所以上面的值還是有可能相同的 //但是可能性很低,上面的例子還是有效的。
使用單例可以讓我們有一個指向實例的統一入口(一般通過MySingleton.getInstance()的方式),這樣我們就不需要直接通過new MySingleton()的方式直接調用啦。這在javascript中也是可以實現的。
在四人幫這本書中,單例的適用場景被描述為下面這些:
必須只有一個類的實例,而且必須可以通過大家都知道的入口讓大家可以訪問到。
當這個唯一的實例需要被之類擴展的時候,用戶可以在不需要修改代碼的情況下擴展它。
第二點指出了我們可能遇到的場景,比如:
mySingleton.getInstance=function(){ if(this._instance==null){ if(isFoo()){ this._instance=new FooSingleton(); }else{ this._instance=new BasicSingleton(); } } return this._instance; }
這里,getInstance變得有些像工廠方法,我們訪問它的時候并不需要更新我們的每一部分代碼。上面的FooSingleton可能是BasicSingleton的之類,并且實現了同樣的接口。
為什么在單例中延遲執行被認為很重要呢?:
在C++中,它被用來讓我們解決動態初始化執行順序的不可預測性,把控制權交給了程序。
需要注意的是區分類的靜態實例和單例的區別是很重要的。盡管單例可以被實現成靜態實例。但是同時也可以延遲構造,不需要消耗資源也不會消耗內存直到需要它的時候再初始化。
如果我們有一個可以被直接初始化的靜態對象,我們需要確保代碼是按照順序執行的。(比如,車的對象初始化的時候車輪必須已經存在)并且它在你有很多資源文件的時候不會變大。
單例和靜態對象都很有用,但是不能過度使用。就像不能過度使用其他模式一樣。
實踐中,當我們在整個系統中只需要一個對象與其他對象通信的時候,單例模式是非常有用的。下面就是單例在上下文中使用模式的一個例子:
var SingletonTester = (function () { // options: an object containing configuration options for the singleton // e.g var options = { name: "test", pointX: 5}; function Singleton( options ) { // set options to the options supplied // or an empty object if none are provided options = options || {}; // set some properties for our singleton this.name = "SingletonTester"; this.pointX = options.pointX || 6; this.pointY = options.pointY || 10; } // our instance holder var instance; // an emulation of static variables and methods var _static = { name: "SingletonTester", // Method for getting an instance. It returns // a singleton instance of a singleton object getInstance: function( options ) { if( instance === undefined ) { instance = new Singleton( options ); } return instance; } }; return _static; })(); var singletonTest = SingletonTester.getInstance({ pointX: 5 }); // Log the output of pointX just to verify it is correct // Outputs: 5 console.log( singletonTest.pointX );
盡管單例在這里使用時有效的,但是經常當我們需要在javascript中使用它的時候,往往意味著我們應該重新審視我們的設計啦。
他們往往意味著系統的模塊要不就是耦合過緊啦,要么邏輯延伸的太大啦。單例的使用往往會讓測試變得更加困難,因為存在隱藏依賴,難以創建多個實例,難以找到根依賴等問題。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86156.html
摘要:原文鏈接譯文原鏈譯我最喜歡的設計模式我最喜歡的設計模式我覺得聊一下我愛用的設計模式應該很有意思。我是一步一步才定下來的,經過一段時間從各種來源吸收和適應直到達到一個能提供我所需的靈活性的模式。 原文鏈接:My Favorite JavaScript Design Pattern譯文原鏈:【譯】我最喜歡的 JavaScript 設計模式 我最喜歡的 JavaScript 設計模式 我覺得...
摘要:不符合設計模式中的單一職責的概念。引入代理實現單例模式引入代理實現單例模式的特點我們負責管理單例的邏輯移到了代理類中。的單例模式對比在以上的代碼中實現的單例模式都混入了傳統面向對象語言的特點。 聲明:這個系列為閱讀《JavaScript設計模式與開發實踐》 ----曾探@著一書的讀書筆記 1.單例模式的特點和定義 保證一個類僅有一個實例,并且提供一個訪問它的全局訪問點。 2.傳統面向對...
摘要:觀察構造函數的代碼,該構造函數實際上負責了兩件事情第一是創建對象和執行初始化方法,第二是保證只有一個對象。惰性單例在實際開發中非常有用,是單例模式的重點。 單例模式 單例模式的定義是: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 單例模式是一種常用的模式,有一些對象我們往往只需要一個,比如線程池、全局緩存、瀏覽器的window對象等。例如,當我們點擊登錄按鈕時,頁面會彈出一...
摘要:本系列為設計模式與開發實踐作者曾探學習總結,如想深入了解,請支持作者原版單例模式實現單例模式單例模式的定義是保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 本系列為《JavaScript設計模式與開發實踐》(作者:曾探)學習總結,如想深入了解,請支持作者原版 單例模式 實現單例模式 單例模式的定義是:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。單例模式是一種常用的模式...
摘要:原文博客地址單例模式系統中被唯一使用,一個類只有一個實例。中的單例模式利用閉包實現了私有變量兩者是否相等弱類型,沒有私有方法,使用者還是可以直接一個,也會有方法分割線不是單例最簡單的單例模式,就是對象。 原文博客地址:https://finget.github.io/2018/11/06/single/ 單例模式 系統中被唯一使用,一個類只有一個實例。實現方法一般是先判斷實例是否存在,...
閱讀 1155·2023-04-25 17:28
閱讀 3531·2021-10-14 09:43
閱讀 3954·2021-10-09 10:02
閱讀 1942·2019-08-30 14:04
閱讀 3128·2019-08-30 13:09
閱讀 3269·2019-08-30 12:53
閱讀 2896·2019-08-29 17:11
閱讀 1822·2019-08-29 16:58