摘要:現(xiàn)在讓我們?cè)O(shè)置溫度值并將其增加減少幾次小結(jié)在中,單例模式根據(jù)是否懶漢模式餓漢模式以及是否線程安全,分為很多種實(shí)現(xiàn)方式。參考設(shè)計(jì)模式與開發(fā)實(shí)踐設(shè)計(jì)模式
Back in 1994, a book was authored by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides that discusses 23 desgin patterns, titled Design Patterns: Elements of Resuable Object-Oriented Software. You may have heard of this book or the authors as Gang of Four (GoF).單例模式
單例模式(Singleton Pattern)是最簡(jiǎn)單的設(shè)計(jì)模式之一。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型 (Creational) 模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
這種模式涉及到一個(gè)單一的類,該類負(fù)責(zé)創(chuàng)建自己的對(duì)象,同時(shí)確保只有單個(gè)對(duì)象被創(chuàng)建。這個(gè)類提供了一種訪問(wèn)其唯一的對(duì)象的方式,可以直接訪問(wèn),不需要實(shí)例化該類的對(duì)象。
注意:
單例類只能有一個(gè)實(shí)例。
單例類必須自己創(chuàng)建自己的唯一實(shí)例。
單例類必須給所有其他對(duì)象提供這一實(shí)例。
單例模式是一種常用的模式,有一些對(duì)象我們往往只需要一個(gè),比如線程池、全局緩存、瀏覽器中的 window 對(duì)象等。在 JavaScript 開發(fā)中,單例模式的用途同樣非常廣泛。試想一下,當(dāng)我們單擊登錄按鈕的時(shí)候,頁(yè)面中會(huì)出現(xiàn)一個(gè)登錄浮窗,而這個(gè)登錄浮窗是唯一的,無(wú)論單擊多少次登錄按鈕,這個(gè)浮窗都只會(huì)被創(chuàng)建一次,那么這個(gè)登錄浮窗就適合用單例模式來(lái)創(chuàng)建。
關(guān)鍵點(diǎn)意圖:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
主要解決:一個(gè)全局使用的類頻繁地創(chuàng)建與銷毀。
何時(shí)使用:當(dāng)您想控制實(shí)例數(shù)目,節(jié)省系統(tǒng)資源的時(shí)候。
如何解決:判斷系統(tǒng)是否已經(jīng)有這個(gè)單例,如果有則返回,如果沒(méi)有則創(chuàng)建。
關(guān)鍵代碼:構(gòu)造函數(shù)是私有的。
UML我們將創(chuàng)建一個(gè) SingleObject 類。SingleObject 類有它的私有構(gòu)造函數(shù)和本身的一個(gè)靜態(tài)實(shí)例。
SingleObject 類提供了一個(gè)靜態(tài)方法,供外界獲取它的靜態(tài)實(shí)例。SingletonPatternDemo,我們的演示類使用 SingleObject 類來(lái)獲取 SingleObject 對(duì)象。
ES5 面向?qū)ο?/b>要實(shí)現(xiàn)一個(gè)標(biāo)準(zhǔn)的單例模式并不復(fù)雜,無(wú)非是用一個(gè)變量來(lái)標(biāo)志當(dāng)前是否已經(jīng)為某個(gè)類創(chuàng)建過(guò)對(duì)象,如果是,則在下一次獲取該類的實(shí)例時(shí),直接返回之前創(chuàng)建的對(duì)象。代碼如下:
var Singleton = function(name) { this.name = name } Singleton.prototype.getName = function() { alert(this.name) } Singleton.getInstance = (function() { var instance = null return function(name) { if (!instance) { instance = new Singleton(name) } return instance } })() var a = Singleton.getInstance( "sven1" ); var b = Singleton.getInstance( "sven2" ); alert ( a === b ); // true
我們通過(guò) Singleton.getInstance 來(lái)獲取 Singleton 類的唯一對(duì)象,這種方式相對(duì)簡(jiǎn)單,但有 一個(gè)問(wèn)題,就是增加了這個(gè)類的“不透明性”,Singleton 類的使用者必須知道這是一個(gè)單例類, 跟以往通過(guò) new XXX 的方式來(lái)獲取對(duì)象不同,這里偏要使 Singleton.getInstance 來(lái)獲取對(duì)象。
上面單例模式的實(shí)現(xiàn),更多的是接近傳統(tǒng)面向?qū)ο笳Z(yǔ)言中的實(shí)現(xiàn),單例對(duì)象從 “類” 中創(chuàng)建而來(lái)。在以類為中心的語(yǔ)言中,這是很自然的做法。比如在 Java 中,如果需要某個(gè)對(duì)象,就必須先定義一個(gè)類,對(duì)象總是從類中創(chuàng)建而來(lái)的。
class-free但 JavaScript 其實(shí)是一門無(wú)類(class-free)語(yǔ)言,也正因?yàn)槿绱?,生搬單例模式的概念并無(wú)意義。在 JavaScript 中創(chuàng)建對(duì)象的方法非常簡(jiǎn)單,既然我們只需要一個(gè)“唯一”的對(duì)象,為什 么要為它先創(chuàng)建一個(gè)“類” 呢?這無(wú)異于穿棉衣洗澡,傳統(tǒng)的單例模式實(shí)現(xiàn)在 JavaScript 中并 不適用。
1.使用命名空間
適當(dāng)?shù)厥褂妹臻g,并不會(huì)杜絕全局變量,但可以減少全局變量的數(shù)量。 最簡(jiǎn)單的方法依然是用對(duì)象字面量的方式:
var namespace1 = { a: function() { alert(1) }, b: function() { alert(2) }, }
2.使用閉包封裝私有變量
這種方法把一些變量封裝在閉包的內(nèi)部,只暴露一些接口跟外界通信:
var namespace = { getSingleton: (function() { // BEGIN iife var singleton return function() { if (!singleton) { singleton = { amethod: function() { console.log("amethod") }, } } return singleton } })(), // END iife } // Invoke: namespace.getSingleton().amethod()ES6
ES6 里有了模塊和類的概念,實(shí)現(xiàn)起來(lái)會(huì)變得不一樣:
const singleton = Symbol(); const singletonEnforcer = Symbol(); class SingletonEnforcer { constructor(enforcer) { if (enforcer !== singletonEnforcer) { throw new Error("Cannot construct singleton"); } this._type = "SingletonEnforcer"; } static get instance() { if (!this[singleton]) { this[singleton] = new SingletonEnforcer(singletonEnforcer); } return this[singleton]; } singletonMethod() { return "singletonMethod"; } static staticMethod() { return "staticMethod"; } get type() { return this._type; } set type(value) { this._type = value; } } export default SingletonEnforcer;Typescript
TypeScript 中有了 private等概念,實(shí)現(xiàn)起來(lái)會(huì)更加有趣。
讓我們想象一下,我們想要一個(gè)跟蹤溫度的類。在這個(gè)系統(tǒng)中,我們希望有一個(gè)入口,可以改變溫度。這就是 Singleton類 的樣子:
class Singleton { private static instance: Singleton; private _temperature: number; private constructor() { } static getInstance() { if (!Singleton.instance) { Singleton.instance = new Singleton(); Singleton.instance._temperature = 0; } return Singleton.instance; } get temperature(): number { return this._temperature; } set temperature(score) { this._temperature = score; } increaseTemperature(): number { return this._temperature += 1; } decreaseTemperature(): number { return this._temperature -= 1; } } const myInstance = Singleton.getInstance(); console.log(myInstance.temperature); // 0
上面的實(shí)現(xiàn)有一下幾點(diǎn)需要注意:
構(gòu)造函數(shù) constructor 前面使用了 private 修飾:這意味著我們將無(wú)法使用 new 關(guān)鍵字實(shí)例化該類。
我們首先檢查我們是否有一個(gè)類的實(shí)例 instance,如果沒(méi)有,我們將創(chuàng)建并返回實(shí)例本身。
如果使用 new 關(guān)鍵字創(chuàng)建對(duì)象:
const myInstance = new Singleton(); // Constructor of class "Singleton" is private and only accessible within the class declaration.
根據(jù)上面的例子,我們也可以訪問(wèn) temperature 屬性。現(xiàn)在讓我們?cè)O(shè)置溫度值并將其增加/減少幾次:
console.log(myInstance.temperature = 25); // 25 console.log(myInstance.increaseTemperature()); // 26 console.log(myInstance.increaseTemperature()); // 27 console.log(myInstance.decreaseTemperature()); // 26小結(jié)
在 java 中,單例模式根據(jù)是否 lazy loading (懶漢模式/餓漢模式)以及是否線程安全,分為很多種實(shí)現(xiàn)方式。而在 JS 中,我們不用關(guān)注線程安全的問(wèn)題,因此無(wú)論是代碼復(fù)雜度還是實(shí)現(xiàn)難度都會(huì)低很多。
參考es6-design-patterns
Singleton pattern in ES6
The Singleton pattern in JavaScript: not needed
JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐
設(shè)計(jì)模式
Singleton Pattern in TypeScript
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/104971.html
摘要:前言講起前端,我們就不能不講與,在這兩種技術(shù)廣泛應(yīng)用的今天,他們的擴(kuò)展也是層出不窮,的擴(kuò)展有等,的超集有等。如下注意你的樣式文件一定要在引入前先引入。截止目前,已經(jīng)發(fā)布了最新的版本。 前言:講起前端,我們就不能不講CSS與Javascript,在這兩種技術(shù)廣泛應(yīng)用的今天,他們的擴(kuò)展也是層出不窮,css的擴(kuò)展有Less、Sass、Stylus等,js的超集有Typescript等。今天我們就簡(jiǎn)...
摘要:新項(xiàng)目起手式最后更新于,技術(shù)文具有時(shí)效性,請(qǐng)知悉我知道你們?cè)缇拖胗蒙蠌?qiáng)類型了還有后續(xù)進(jìn)階篇安裝安裝依賴配置添加添加讓識(shí)別改造文件什么是是的強(qiáng)類型版本。是的超集,這意味著他支持所有的語(yǔ)法。與此同時(shí),也是的超集,的也宣布采用進(jìn)行開發(fā)。 vue + typescript 新項(xiàng)目起手式 最后更新于2018-06-30,技術(shù)文具有時(shí)效性,請(qǐng)知悉 我知道你們?cè)缇拖胗蒙?vue + ts 強(qiáng)類型...
摘要:裝飾者模式裝飾者模式就是動(dòng)態(tài)的給類或?qū)ο笤黾庸δ艿脑O(shè)計(jì)模式。下的實(shí)現(xiàn)里的裝飾器目前處在建議征集的第二階段,不被瀏覽器所支持,如果想要提前使用這個(gè)新特性就需要,等工具進(jìn)行轉(zhuǎn)譯。這里介紹下的用法。 1.1、裝飾者模式 裝飾者模式就是動(dòng)態(tài)的給類或?qū)ο笤黾庸δ艿脑O(shè)計(jì)模式。在程序運(yùn)行時(shí)動(dòng)態(tài)的給一個(gè)具備基礎(chǔ)功能的類或?qū)ο筇砑有碌墓δ?,并且不?huì)改變會(huì)破壞基礎(chǔ)類和對(duì)象的功能。先提煉出產(chǎn)品的最小可用產(chǎn)品...
摘要:為了由簡(jiǎn)入繁,不妨將這些類型劃分為基本類型復(fù)合類型。以下將漸進(jìn)式的對(duì)的這些類型進(jìn)行了解。實(shí)際上,有一種屬性描述對(duì)象,是通過(guò)獲取的。但無(wú)論如何,類型檢查是可以排除大部分錯(cuò)誤的。在函數(shù)的類型聲明中,繼續(xù)來(lái)鞏固這條規(guī)則的寫法。 幾個(gè)月前把 ES6 的特性都過(guò)了一遍,收獲頗豐。現(xiàn)在繼續(xù)來(lái)看看 TypesScript(下文簡(jiǎn)稱為 TS)。限于經(jīng)驗(yàn),本文一些總結(jié)如有不當(dāng),歡迎指正。 概述 官網(wǎng)有這...
閱讀 2576·2021-08-11 11:16
閱讀 2997·2019-08-30 15:55
閱讀 3399·2019-08-30 12:53
閱讀 1640·2019-08-29 13:28
閱讀 3324·2019-08-28 18:17
閱讀 1029·2019-08-26 12:19
閱讀 2519·2019-08-23 18:27
閱讀 771·2019-08-23 18:17