摘要:原文單例模式被熟知是因?yàn)樗岩粋€(gè)類的實(shí)例化限制在只有一個(gè)對(duì)象。這在中也是可以實(shí)現(xiàn)的。單例和靜態(tài)對(duì)象都很有用,但是不能過度使用。實(shí)踐中,當(dāng)我們?cè)谡麄€(gè)系統(tǒng)中只需要一個(gè)對(duì)象與其他對(duì)象通信的時(shí)候,單例模式是非常有用的。
原文:The Single Pattern
單例模式被熟知是因?yàn)樗岩粋€(gè)類的實(shí)例化限制在只有一個(gè)對(duì)象。傳統(tǒng)的實(shí)現(xiàn)方式是:創(chuàng)建一個(gè)類,這個(gè)類里面有一個(gè)方法在對(duì)象不存在的時(shí)候創(chuàng)造一個(gè)實(shí)例,存在的時(shí)候,只需要返回這個(gè)對(duì)象的引用即可。
單例和靜態(tài)類(或者對(duì)象)是有區(qū)別的,因?yàn)槲覀兛梢匝舆t他們的初始化。因?yàn)樗麄冃枰恍┰诔跏蓟臅r(shí)候不能獲得的信息。他們沒有提供一種方式讓不知道他們之前引用的代碼去獲取他們。這是因?yàn)橛蓡卫祷氐募炔皇菍?duì)象也不是類,而是一種結(jié)構(gòu)。想想大括號(hào)形成的不是真正的閉包,函數(shù)作用于提供的閉包才是真正的閉包。
Javascript中,單例作為共享資源的命名空間,它隔離了實(shí)現(xiàn)的代碼和全局變量,為了能夠讓函數(shù)有唯一的一個(gè)入口。
我們可以通過下面的方法實(shí)現(xiàn)單例:
var mySingleton=(function(){ //存儲(chǔ)單例引用的實(shí)例 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 { //如果存在獲取單例實(shí)例的引用 //不存在,創(chuàng)建實(shí)例 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 { //無論什么時(shí)候都創(chuàng)建一個(gè)單例實(shí)例 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 //注意:因?yàn)槲覀兪褂玫氖请S機(jī)數(shù) //所以上面的值還是有可能相同的 //但是可能性很低,上面的例子還是有效的。
使用單例可以讓我們有一個(gè)指向?qū)嵗慕y(tǒng)一入口(一般通過MySingleton.getInstance()的方式),這樣我們就不需要直接通過new MySingleton()的方式直接調(diào)用啦。這在javascript中也是可以實(shí)現(xiàn)的。
在四人幫這本書中,單例的適用場(chǎng)景被描述為下面這些:
必須只有一個(gè)類的實(shí)例,而且必須可以通過大家都知道的入口讓大家可以訪問到。
當(dāng)這個(gè)唯一的實(shí)例需要被之類擴(kuò)展的時(shí)候,用戶可以在不需要修改代碼的情況下擴(kuò)展它。
第二點(diǎn)指出了我們可能遇到的場(chǎng)景,比如:
mySingleton.getInstance=function(){ if(this._instance==null){ if(isFoo()){ this._instance=new FooSingleton(); }else{ this._instance=new BasicSingleton(); } } return this._instance; }
這里,getInstance變得有些像工廠方法,我們?cè)L問它的時(shí)候并不需要更新我們的每一部分代碼。上面的FooSingleton可能是BasicSingleton的之類,并且實(shí)現(xiàn)了同樣的接口。
為什么在單例中延遲執(zhí)行被認(rèn)為很重要呢?:
在C++中,它被用來讓我們解決動(dòng)態(tài)初始化執(zhí)行順序的不可預(yù)測(cè)性,把控制權(quán)交給了程序。
需要注意的是區(qū)分類的靜態(tài)實(shí)例和單例的區(qū)別是很重要的。盡管單例可以被實(shí)現(xiàn)成靜態(tài)實(shí)例。但是同時(shí)也可以延遲構(gòu)造,不需要消耗資源也不會(huì)消耗內(nèi)存直到需要它的時(shí)候再初始化。
如果我們有一個(gè)可以被直接初始化的靜態(tài)對(duì)象,我們需要確保代碼是按照順序執(zhí)行的。(比如,車的對(duì)象初始化的時(shí)候車輪必須已經(jīng)存在)并且它在你有很多資源文件的時(shí)候不會(huì)變大。
單例和靜態(tài)對(duì)象都很有用,但是不能過度使用。就像不能過度使用其他模式一樣。
實(shí)踐中,當(dāng)我們?cè)谡麄€(gè)系統(tǒng)中只需要一個(gè)對(duì)象與其他對(duì)象通信的時(shí)候,單例模式是非常有用的。下面就是單例在上下文中使用模式的一個(gè)例子:
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 );
盡管單例在這里使用時(shí)有效的,但是經(jīng)常當(dāng)我們需要在javascript中使用它的時(shí)候,往往意味著我們應(yīng)該重新審視我們的設(shè)計(jì)啦。
他們往往意味著系統(tǒng)的模塊要不就是耦合過緊啦,要么邏輯延伸的太大啦。單例的使用往往會(huì)讓測(cè)試變得更加困難,因?yàn)榇嬖陔[藏依賴,難以創(chuàng)建多個(gè)實(shí)例,難以找到根依賴等問題。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/86156.html
摘要:原文鏈接譯文原鏈譯我最喜歡的設(shè)計(jì)模式我最喜歡的設(shè)計(jì)模式我覺得聊一下我愛用的設(shè)計(jì)模式應(yīng)該很有意思。我是一步一步才定下來的,經(jīng)過一段時(shí)間從各種來源吸收和適應(yīng)直到達(dá)到一個(gè)能提供我所需的靈活性的模式。 原文鏈接:My Favorite JavaScript Design Pattern譯文原鏈:【譯】我最喜歡的 JavaScript 設(shè)計(jì)模式 我最喜歡的 JavaScript 設(shè)計(jì)模式 我覺得...
摘要:不符合設(shè)計(jì)模式中的單一職責(zé)的概念。引入代理實(shí)現(xiàn)單例模式引入代理實(shí)現(xiàn)單例模式的特點(diǎn)我們負(fù)責(zé)管理單例的邏輯移到了代理類中。的單例模式對(duì)比在以上的代碼中實(shí)現(xiàn)的單例模式都混入了傳統(tǒng)面向?qū)ο笳Z言的特點(diǎn)。 聲明:這個(gè)系列為閱讀《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》 ----曾探@著一書的讀書筆記 1.單例模式的特點(diǎn)和定義 保證一個(gè)類僅有一個(gè)實(shí)例,并且提供一個(gè)訪問它的全局訪問點(diǎn)。 2.傳統(tǒng)面向?qū)?..
摘要:觀察構(gòu)造函數(shù)的代碼,該構(gòu)造函數(shù)實(shí)際上負(fù)責(zé)了兩件事情第一是創(chuàng)建對(duì)象和執(zhí)行初始化方法,第二是保證只有一個(gè)對(duì)象。惰性單例在實(shí)際開發(fā)中非常有用,是單例模式的重點(diǎn)。 單例模式 單例模式的定義是: 保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。 單例模式是一種常用的模式,有一些對(duì)象我們往往只需要一個(gè),比如線程池、全局緩存、瀏覽器的window對(duì)象等。例如,當(dāng)我們點(diǎn)擊登錄按鈕時(shí),頁面會(huì)彈出一...
摘要:本系列為設(shè)計(jì)模式與開發(fā)實(shí)踐作者曾探學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版單例模式實(shí)現(xiàn)單例模式單例模式的定義是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。 本系列為《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》(作者:曾探)學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版 單例模式 實(shí)現(xiàn)單例模式 單例模式的定義是:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。單例模式是一種常用的模式...
摘要:原文博客地址單例模式系統(tǒng)中被唯一使用,一個(gè)類只有一個(gè)實(shí)例。中的單例模式利用閉包實(shí)現(xiàn)了私有變量?jī)烧呤欠裣嗟热躅愋?,沒有私有方法,使用者還是可以直接一個(gè),也會(huì)有方法分割線不是單例最簡(jiǎn)單的單例模式,就是對(duì)象。 原文博客地址:https://finget.github.io/2018/11/06/single/ 單例模式 系統(tǒng)中被唯一使用,一個(gè)類只有一個(gè)實(shí)例。實(shí)現(xiàn)方法一般是先判斷實(shí)例是否存在,...
閱讀 1240·2023-04-25 17:28
閱讀 3910·2021-10-14 09:43
閱讀 4203·2021-10-09 10:02
閱讀 2018·2019-08-30 14:04
閱讀 3201·2019-08-30 13:09
閱讀 3334·2019-08-30 12:53
閱讀 2981·2019-08-29 17:11
閱讀 1879·2019-08-29 16:58