摘要:此時我們創建的對象內保存靜態變量通過取值器訪問,最后將這個對象作為一個單例放在全局空間里面作為靜態變量單例對象供他人使用。
單例模式
又被稱為單體模式,是只允許實例化一次的對象類。有時我們也用一個對象來規劃一個命名空間,井井有條的管理對象上面的屬性和方法。
傳統的面向對象語言中單例模式的實現,均是單例對象從“類”中創建而來,在以類為中心的語言中,這是很常見的做法。如果需要某個對象,就必須先定義一個類,對象總是從類中創建而來。但是在JavaScript中卻是并不需要這樣做。
單例模式的核心是確保只有一個實例,并提供全局訪問。
全局變量不是單例模式,但是在JavaScript中,我們經常會把全局變量當成單例來使用。如瀏覽器中的window對象。再比如:
var a = {};
當用這種方式創建對象a 時,對象a 確實是獨一無二的。如果a 變量被聲明在全局作用域下,
則我們可以在代碼中的任何位置使用這個變量,全局變量提供給全局訪問是理所當然的。這樣就滿足了單例模式的兩個條件。
但是全局變量存在很多問題,它很容易造成命名空間污染。在大中型項目中,如果不加以限制和管理,程序中可能存在很多這樣的變量。JavaScript 中的變量也很容易被不小心覆蓋,相信每個JavaScript 程序員都曾經歷過變量沖突的痛苦,就像上面的對象var a = {};,隨時有可能被
別人覆蓋。
適當地使用命名空間,并不會杜絕全局變量,但可以減少全局變量的數量。
最簡單的方法依然是用對象字面量的方式:
var namespace1 = { a: function(){ alert (1); }, b: function(){ alert (2); } };
把a 和b 都定義為namespace1 的屬性,這樣可以減少變量和全局作用域打交道的機會。另外
我們還可以動態地創建命名空間,代碼如下(引自Object-Oriented JavaScrtipt 一書):
var MyApp = {}; MyApp.namespace = function( name ){ var parts = name.split( "." ); var current = MyApp; for ( var i in parts ){ if ( !current[ parts[ i ] ] ){ current[ parts[ i ] ] = {}; } current = current[ parts[ i ] ]; } }; MyApp.namespace( "event" ); MyApp.namespace( "dom.style" ); console.dir( MyApp ); // 上述代碼等價于: var MyApp = { event: {}, dom: { style: {} } };模塊管理
其實在JavaScript中單例模式除了定義命名空間外,還有一個作用,就是通過單例模式來管理代碼庫的各個模塊。這樣我們就可以通過單例模式來創建一個自己的小型代碼方法庫,進而來規范我們自己代碼庫的各個模塊的功能和方法。比如:
var OurLib = { // 公共模塊部分 Util: { util_method1: function(){}, util_method2: function(){} // ... }, // 工具模塊部分 Tool: { tool_method1: function(){}, tool_method2: function(){} // ... }, // ajax模塊部分 Ajax: { get: function(){}, post: function() // ... }, others: { // ... } }維護靜態變量
我們知道的是JavaScript中并沒有static這類關鍵字(暫不考慮es6等新語法),所以定義任何變量理論上都是可以更改的,所以在JavaScript中實現創建靜態變量又是很重要的。根據靜態變量只能訪問不能修改并且創建后就能使用這一特點,可以如此來實現:能訪問的變量定義的方式有很多,比如定義在全局空間中,或者定義一個函數內部,并定義一個特權方法來進行訪問等。但是既然不能修改,定義在全局空間里面就不行了,我們可以將變量放在一個函數內部,通過特權方法進行訪問,并且不提供賦值變量的方法只提供獲取變量的方法,就可以了。由于放在了函數內部,如果想要能夠供外界訪問,我們需要讓創建的函數執行一遍。此時我們創建的對象內保存靜態變量通過取值器訪問,最后將這個對象作為一個單例放在全局空間里面作為靜態變量單例對象供他人使用。如:
var Conf = (function(){ // 私有變量 var conf = { MAX_NUM: 100, MIN_NUM: 1, COUNT: 1000 } // 返回取值器對象 return { // 取值器方法 get: function(name) { return conf[name] ? conf[name] : null; } } })();
這樣我們就可以來維護我們的靜態變量了。
惰性單例有時候對于單例對象我們需要延遲創建,所以在單例中還存在一種延遲創建的形式,也被稱為“惰性創建”。例子如下:
// 惰性載入單例 var LazySingle = (function(){ // 單例實例引用 var _instance = null; // 單例 function Single() { /* 這里定義私有屬性和方法 */ return { publicMethod: function(){}, publicProperty: "1.0" } } // 獲取單例對象接口 return function(){ // 如果未創建單例,將創建單例 if(!_instance) { _instance = Single(); } // 返回單例 return _instance; } })();總結
通過上面對于單例模式在JavaScript中的一些提現形式,我們對于單例模式的使用有了一個基本的了解,同樣也理解了為什么很多代碼庫都提供一個變量(當然還有一些還提供了簡單的別名,如jQuery的$別名,underscore的_別名等)來管理每個模塊的方式。這也為我們以后來設計我們自己的公共代碼庫提供了參考。但是同樣的,也能發現,單例模式在JavaScript中是有別于其他的面向對象語言中的實現方式的。
最后,歡迎大家拍磚,但是請輕拍:)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90629.html
摘要:但是,這并不是采用單例的唯一原因。使用命名空間單例模式也被稱為模塊設計模式。函數內部聲明了一些局部函數和或變量。緊隨函數聲明放置即可立即執行外部函數,并將所得的對象文字費賠給變量。 JavaScript設計模式-第一部分:單例模式、組合模式和外觀模式 設計模式是一些可靠的編程方式,有助于保證代碼更加易于維護、擴展及分離,所有設計模式在創建大型JavaScript應用程序時均不可或缺 單...
摘要:不符合設計模式中的單一職責的概念。引入代理實現單例模式引入代理實現單例模式的特點我們負責管理單例的邏輯移到了代理類中。的單例模式對比在以上的代碼中實現的單例模式都混入了傳統面向對象語言的特點。 聲明:這個系列為閱讀《JavaScript設計模式與開發實踐》 ----曾探@著一書的讀書筆記 1.單例模式的特點和定義 保證一個類僅有一個實例,并且提供一個訪問它的全局訪問點。 2.傳統面向對...
摘要:停更許久,近期計劃更新設計模式系列。單例模式是創建型設計模式的一種。雖然它不是正規的單例模式,但不可否認確實具備類單例模式的特點。適用場景單例模式的特點,意圖解決維護一個全局實例對象。 停更許久,近期計劃更新:設計模式系列。 showImg(https://segmentfault.com/img/bVbt7uw?w=800&h=600); 單例模式:限制類實例化次數只能一次,一個類只...
摘要:觀察構造函數的代碼,該構造函數實際上負責了兩件事情第一是創建對象和執行初始化方法,第二是保證只有一個對象。惰性單例在實際開發中非常有用,是單例模式的重點。 單例模式 單例模式的定義是: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。 單例模式是一種常用的模式,有一些對象我們往往只需要一個,比如線程池、全局緩存、瀏覽器的window對象等。例如,當我們點擊登錄按鈕時,頁面會彈出一...
摘要:在面向對象的語言中,比如,等,單例模式通常是定義類時將構造函數設為,保證對象不能在外部被出來,同時給類定義一個靜態的方法,用來獲取或者創建這個唯一的實例。 萬事開頭難,作為正經歷菜鳥賽季的前端player,已經忘記第一次告訴自己要寫一些東西出來是多久以的事情了。。。如果,你也和我一樣,那就像我一樣,從現在開始,從看到這篇文章開始,打開電腦,敲下你的第一篇文章(或者任何形式的文字)吧。 ...
閱讀 2270·2019-08-30 15:56
閱讀 3108·2019-08-30 13:48
閱讀 1123·2019-08-30 10:52
閱讀 1490·2019-08-29 17:30
閱讀 417·2019-08-29 13:44
閱讀 3528·2019-08-29 12:53
閱讀 1113·2019-08-29 11:05
閱讀 2667·2019-08-26 13:24