摘要:文章系列設(shè)計(jì)模式單例模式設(shè)計(jì)模式策略模式設(shè)計(jì)模式代理模式概念單例模式的定義是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。在開(kāi)發(fā)中,單例模式的用途同樣非常廣泛。
前言
本系列文章主要根據(jù)《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》整理而來(lái),其中會(huì)加入了一些自己的思考。希望對(duì)大家有所幫助。
文章系列js設(shè)計(jì)模式--單例模式
js設(shè)計(jì)模式--策略模式
js設(shè)計(jì)模式--代理模式
概念單例模式的定義是:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
UML類圖 場(chǎng)景單例模式是一種常用的模式,有一些對(duì)象我們往往只需要一個(gè),比如線程池、全局緩存、瀏 覽器中的 window 對(duì)象等。
在 JavaScript 開(kāi)發(fā)中,單例模式的用途同樣非常廣泛。試想一下,當(dāng)我們單擊登錄按鈕的時(shí)候,頁(yè)面中會(huì)出現(xiàn)一個(gè)登錄浮窗,而這個(gè)登錄浮窗是唯一的,無(wú)論單擊多少 次登錄按鈕,這個(gè)浮窗都只會(huì)被創(chuàng)建一次,那么這個(gè)登錄浮窗就適合用單例模式來(lái)創(chuàng)建。
優(yōu)缺點(diǎn)優(yōu)點(diǎn):創(chuàng)建對(duì)象和管理單例的職責(zé)被分布在兩個(gè)不同的方法中
實(shí)現(xiàn) 1. 我們的第一個(gè)單例var instance = null var getInstance = function(arg) { if (!instance) { instance = arg } return instance } var a = getInstance("a") var b = getInstance("b") console.log(a===b)
這種定義一個(gè)全局變量的方式非常不優(yōu)雅,也不好復(fù)用代碼
2. 利用閉包實(shí)現(xiàn)單例var Singleton = function( name ){ this.name = name; }; Singleton.getInstance = (function(){ var instance = null; return function( name ){ if ( !instance ){ instance = new Singleton( name ); } return instance; } })(); var a = Singleton.getInstance("a") var b = Singleton.getInstance("b") console.log(a===b)
有些同學(xué)可能對(duì)閉包不大理解,下面用函數(shù)實(shí)現(xiàn)一下
3. 利用函數(shù)實(shí)現(xiàn)單例function Singleton(name) { this.name = name this.instance = null } Singleton.getInstance = function(name) { if (!this.instance) { this.instance = new Singleton(name) } return this.instance } var a = Singleton.getInstance("a") var b = Singleton.getInstance("b") console.log(a===b)
2,3這兩種方式也有缺點(diǎn),就是我們必須調(diào)用getInstance來(lái)創(chuàng)建對(duì)象,一般我們創(chuàng)建對(duì)象都是利用new操作符
4. 透明的單例模式var Singleton = (function() { var instance Singleton = function(name) { if (instance) return instance this.name = name return instance = this } return Singleton })() var a = new Singleton("a") var b = new Singleton("b") console.log(a===b)
這中方法也有點(diǎn)缺點(diǎn):不符合單一職責(zé)原則,這個(gè)對(duì)象其實(shí)負(fù)責(zé)了兩個(gè)功能:?jiǎn)卫蛣?chuàng)建對(duì)象
下面我們分離這兩個(gè)職責(zé)
5. 利用代理實(shí)現(xiàn)單例var People = function(name) { this.name = name } var Singleton = (function() { var instance Singleton = function(name) { if (instance) return instance return instance = new People(name) } return Singleton })() var a = new Singleton("a") var b = new Singleton("b") console.log(a===b)
這中方法也有點(diǎn)缺點(diǎn):代碼不能復(fù)用。如果我們有另外一個(gè)對(duì)象也要利用單例模式,那我們不得不寫(xiě)重復(fù)的代碼
6. 提供通用的單例var People = function(name) { this.name = name } var Singleton = function(Obj) { var instance Singleton = function() { if (instance) return instance return instance = new Obj(arguments) } return Singleton } var peopleSingleton = Singleton(People) var a = new peopleSingleton("a") var b = new peopleSingleton("b") console.log(a===b)
到這里已經(jīng)比較完美了,等等這只是es5的寫(xiě)法,下面我們用es6來(lái)實(shí)現(xiàn)一下
7. es6單例模式class People { constructor(name) { if (typeof People.instance === "object") { return People.instance; } People.instance = this; this.name = name return this; } } var a = new People("a") var b = new People("b") console.log(a===b)比較以上幾種實(shí)現(xiàn)
用全局變量的第1種方法,應(yīng)該摒棄
用閉包實(shí)現(xiàn)的第2種方式,instance 實(shí)例對(duì)象總是在我們調(diào)用 Singleton.getInstance 的時(shí)候才被創(chuàng)建,應(yīng)該摒棄
其他方式都是惰性單例(在需要時(shí)才創(chuàng)建)
js的特殊性我們都知道:JavaScript 其實(shí)是一門無(wú)類(class-free)語(yǔ)言,,生搬單例模式的概念并無(wú)意義。
單例模式的核心是確保只有一個(gè)實(shí)例,并提供全局訪問(wèn)。
我們可以用一下幾種方式來(lái)另類實(shí)現(xiàn)
1. 全局變量比如var a = {},這時(shí)全局就只有一個(gè)a對(duì)象
但全局變量存在很多問(wèn)題,它很容易造成命名空間污染,我們用以下兩種方式解決
var namespace1 = { a: function () { alert(1); }, b: function () { alert(2); } };
另外我們還可以動(dòng)態(tài)創(chuàng)建命名空間
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); // 上述代碼等價(jià)于: var MyApp = { event: {}, dom: { style: {} } };3. 閉包
var user = (function () { var __name = "sven", __age = 29; return { getUserInfo: function () { return __name + "-" + __age; } } })();例子 登錄框
下面我們來(lái)實(shí)現(xiàn)一個(gè)點(diǎn)擊登錄按鈕彈出登錄框的例子
粗糙的實(shí)現(xiàn)上面這種方式如果用戶沒(méi)有點(diǎn)擊登錄按鈕,也會(huì)在一開(kāi)始就創(chuàng)建登錄框
改進(jìn)這種方式每次點(diǎn)擊按鈕都會(huì)創(chuàng)建一個(gè)登錄框
再改進(jìn)var createLoginLayer = (function () { var div; return function () { if (!div) { div = document.createElement("div"); div.innerHTML = "我是登錄浮窗"; div.style.display = "none"; document.body.appendChild(div); } return div; } })(); document.getElementById("loginBtn").onclick = function () { var loginLayer = createLoginLayer(); loginLayer.style.display = "block"; };
這種方式不夠通用,不符合單一職責(zé)原則
再再改進(jìn)var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)); } }; var createLoginLayer = function () { var div = document.createElement("div"); div.innerHTML = "我是登錄浮窗"; div.style.display = "none"; document.body.appendChild(div); return div; }; var createSingleLoginLayer = getSingle(createLoginLayer); document.getElementById("loginBtn").onclick = function () { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block"; }; //下面我們?cè)僭囋噭?chuàng)建唯一的iframe 用于動(dòng)態(tài)加載第三方頁(yè)面: var createSingleIframe = getSingle(function () { var iframe = document.createElement("iframe"); document.body.appendChild(iframe); return iframe; }); document.getElementById("loginBtn").onclick = function () { var loginLayer = createSingleIframe(); loginLayer.src = "http://baidu.com"; };
至此已經(jīng)完美
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100608.html
摘要:但是如何在對(duì)構(gòu)造函數(shù)使用操作符創(chuàng)建多個(gè)對(duì)象的時(shí)候僅獲取一個(gè)單例對(duì)象呢。單例的實(shí)例引用單例構(gòu)造函數(shù)單例私有屬性和方法暴露出來(lái)的對(duì)象改進(jìn)之前在構(gòu)造函數(shù)中重寫(xiě)自身會(huì)丟失所有在初始定義和重定義之間添加到其中的屬性。 1. 單例模式 單例模式 (Singleton) 的實(shí)現(xiàn)在于保證一個(gè)特定類只有一個(gè)實(shí)例,第二次使用同一個(gè)類創(chuàng)建新對(duì)象的時(shí)候,應(yīng)該得到與第一次創(chuàng)建對(duì)象完全相同的對(duì)象。當(dāng)創(chuàng)建一個(gè)新對(duì)象...
摘要:?jiǎn)卫J秸f(shuō)到單例設(shè)計(jì)模式,中經(jīng)常使用的單例模式通常分兩種,懶漢模式和餓漢模式懶漢模式簡(jiǎn)單寫(xiě)了下私有化構(gòu)造函數(shù)在獲取實(shí)例的方法中返回實(shí)例化對(duì)象雖然很多大佬都寫(xiě)過(guò)啦,但是小生為了加深記憶便再寫(xiě)一遍雖然實(shí)現(xiàn)了單例模式,但是未考慮到線程安全,多個(gè)線 java單例模式 說(shuō)到單例設(shè)計(jì)模式,Java中經(jīng)常使用java的單例模式通常分兩種,懶漢模式和餓漢模式 懶漢模式 class singleDemo...
摘要:什么是設(shè)計(jì)模式設(shè)計(jì)模式是一種能夠被反復(fù)使用,符合面向?qū)ο筇匦缘拇a設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),合理的使用設(shè)計(jì)模式能夠讓你得代碼更容易維護(hù)和可靠設(shè)計(jì)模式的類型共分為創(chuàng)建型模式,結(jié)構(gòu)型模式,行為型模式三種創(chuàng)建型模式創(chuàng)建型模式是對(duì)一個(gè)類的實(shí)例化過(guò)程進(jìn)行了抽象 什么是設(shè)計(jì)模式 設(shè)計(jì)模式是一種能夠被反復(fù)使用,符合面向?qū)ο筇匦缘拇a設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),合理的使用設(shè)計(jì)模式能夠讓你得代碼更容易維護(hù)和可靠設(shè)計(jì)模式的類型...
摘要:什么是單例模式單例模式是一種十分常用但卻相對(duì)而言比較簡(jiǎn)單的單例模式。對(duì)象就是單例模式的體現(xiàn)。總結(jié)單例模式雖然簡(jiǎn)單,但是在項(xiàng)目中的應(yīng)用場(chǎng)景卻是相當(dāng)多的,單例模式的核心是確保只有一個(gè)實(shí)例,并提供全局訪問(wèn)。 1. 什么是單例模式? 單例模式是一種十分常用但卻相對(duì)而言比較簡(jiǎn)單的單例模式。它是指在一個(gè)類只能有一個(gè)實(shí)例,即使多次實(shí)例化該類,也只返回第一次實(shí)例化后的實(shí)例對(duì)象。單例模式不僅能減少不必要...
閱讀 660·2021-11-15 11:39
閱讀 2895·2021-10-08 10:04
閱讀 3259·2019-08-30 10:57
閱讀 3020·2019-08-26 13:25
閱讀 1902·2019-08-26 12:14
閱讀 2633·2019-08-23 15:27
閱讀 2992·2019-08-23 15:18
閱讀 1773·2019-08-23 14:26