摘要:?jiǎn)卫J絾卫J剑步袉巫幽J剑且环N常用的軟件設(shè)計(jì)模式。在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。透明的單例模式利用一個(gè)形成一個(gè)閉包,在里邊通過(guò)變量來(lái)記錄實(shí)例,并返回構(gòu)造函數(shù)。
單例模式
單例模式,也叫單子模式,是一種常用的軟件設(shè)計(jì)模式。在應(yīng)用這個(gè)模式時(shí),單例對(duì)象的類必須保證只有一個(gè)實(shí)例存在。
———來(lái)自維基百科
一個(gè)很典型的應(yīng)用是在點(diǎn)擊登錄按鈕,彈出登錄浮窗,不論點(diǎn)擊多少次登錄按鈕,頁(yè)面始終只會(huì)彈出一個(gè)登錄浮窗。
實(shí)現(xiàn)單例模式思路很簡(jiǎn)單,用一個(gè)變量記錄是否已經(jīng)為某個(gè)類創(chuàng)建過(guò)對(duì)象,如果沒(méi)有則返回新建的對(duì)象,反之則返回之前創(chuàng)建的對(duì)象。
在構(gòu)造器里記錄實(shí)例:var Singleton = function(name) { this.name = name; this.instance = null; }; Singleton.prototype.getName = function() { console.log(this.name); }; Singleton.getInstance = function(name) { if (!this.instance) { this.instance = new Singleton(name); } return this.instance; }; var a = Singleton.getInstance("sean1"); var b = Singleton.getInstance("sean2"); console.log(a === b); // true使用閉包記錄實(shí)例:
var Singleton = function(name) { this.name = name; }; Singleton.prototype.getName = function() { console.log(this.name); }; Singleton.getInstance = (function() { var instance = null; return function(name) { if (!instance) { instance = new Singleton(name); } return instance; }; })(); var a = Singleton.getInstance("sean1"); var b = Singleton.getInstance("sean2"); console.log(a === b); // true
以上方法相對(duì)簡(jiǎn)單,但是Singleton類的使用者必須知道這是一個(gè)單例類,需要調(diào)用getInstance()函數(shù)(而不是new的方式)來(lái)獲取對(duì)象,這也就是增加了“不透明性”。
透明的單例模式利用一個(gè)IIFE形成一個(gè)閉包,在里邊通過(guò)變量instance來(lái)記錄實(shí)例,并返回構(gòu)造函數(shù)。
var CreateDiv = (function() { var instance; var CreateDiv = function(html) { if (instance) { return instance; } this.html = html; this.init(); return (instance = this); }; CreateDiv.prototype.init = function() { var div = document.createElement("div"); div.innerHtml = this.html; document.body.appendChild(div); }; return CreateDiv; })(); var a = new CreateDiv("sean1"); var b = new CreateDiv("sean2"); console.log(a === b); // true
上面完成了一個(gè)透明的單例類的編寫,但還是有缺點(diǎn),增加了一些程序的復(fù)雜度,且閱讀性差。還有重要的一點(diǎn)是違反了“單一職責(zé)原則”,接下來(lái)再改進(jìn)一下。
用代理實(shí)現(xiàn)單例模式其實(shí)就是將實(shí)際的業(yè)務(wù)代碼與負(fù)責(zé)管理單例的代碼分離,管理單例的類就是代理類。
var CreateDiv = function(html) { this.html = html; this.init(); }; CreateDiv.prototype.init = function() { var div = document.createElement("div"); div.innerHtml = this.html; document.body.appendChild(div); }; var ProxySingletonCreateDiv = (function() { var instance; return function(html) { if (!instance) { instance = new CreateDiv(html); } return instance; }; })(); var a1 = new ProxySingletonCreateDiv("sean1"); var b1 = new ProxySingletonCreateDiv("sean2"); console.log(a1 === b1); // true // 如果想要?jiǎng)?chuàng)建多個(gè) div 就直接調(diào)用 CreateDiv 咯 var a2 = new CreateDiv("sean1"); var b2 = new CreateDiv("sean2"); console.log(a2 === b2); // falseJavaScript 中的單例模式
前面提到的幾種實(shí)現(xiàn),更多的是接近傳統(tǒng)面向?qū)ο笳Z(yǔ)言中的實(shí)現(xiàn),但 JavaScript 是一門無(wú)類(class-free)語(yǔ)言,我們只要記住單例模式但核心是 確保只有一個(gè)實(shí)例,并提供全局訪問(wèn)。
全局變量不是單例模式,但它卻滿足單例的條件,所以我們經(jīng)常會(huì)把全局變量當(dāng)成單例來(lái)使用:var a = {};。但是我們都知道全局變量很容易造成命名空間污染、容易被不小心覆蓋等問(wèn)題。我們有必要盡量減少全局變量的使用,即使要,也要將污染降到最低:
使用命名空間
var namespace1 = { a: function() { return 1; }, b: function() { return 2; } }; // 或者動(dòng)態(tài)創(chuàng)建命名空間: var MyApp = {}; MyApp.namespace = function(name) { var parts = name.split("."); var current = MyApp; for (var item of parts) { if (!current[item]) { current[item] = {}; } current = current[item]; } }; MyApp.namespace("event"); MyApp.namespace("dom.style"); console.dir(MyApp);
使用閉包封裝私有變量
var user = (function() { var __name = "sean", __age = 19; return { getUserInfo: function() { return __name + "-" + __age; } }; })();惰性單例
所謂惰性,就是只有在需要的時(shí)候才會(huì)去做。前面提到的也有滿足惰性的實(shí)現(xiàn),不過(guò)是基于“類”的。下面來(lái)看一下文章開(kāi)頭提到的那個(gè)典型的應(yīng)用實(shí)現(xiàn):
上面的代碼完成了惰性單例的實(shí)現(xiàn),但仍然違反了單一職責(zé)原則,如果我們下次不是創(chuàng)建一個(gè)登錄浮窗而是別的元素呢,請(qǐng)往后看通用的惰性單例。
通用的惰性單例// 定義一個(gè)管理單例的函數(shù): var getSingle = function(fn) { var result; return function() { return result || (result = fn.apply(this, arguments)) } } // 定義創(chuàng)建浮窗的函數(shù): 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("btn").onclick = function() { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block"; };參考
曾探. JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐 (圖靈原創(chuàng)) (Chinese Edition)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/106810.html
摘要:但是如何在對(duì)構(gòu)造函數(shù)使用操作符創(chuàng)建多個(gè)對(duì)象的時(shí)候僅獲取一個(gè)單例對(duì)象呢。單例的實(shí)例引用單例構(gòu)造函數(shù)單例私有屬性和方法暴露出來(lái)的對(duì)象改進(jìn)之前在構(gòu)造函數(shù)中重寫自身會(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)單寫了下私有化構(gòu)造函數(shù)在獲取實(shí)例的方法中返回實(shí)例化對(duì)象雖然很多大佬都寫過(guò)啦,但是小生為了加深記憶便再寫一遍雖然實(shí)現(xiàn)了單例模式,但是未考慮到線程安全,多個(gè)線 java單例模式 說(shuō)到單例設(shè)計(jì)模式,Java中經(jīng)常使用java的單例模式通常分兩種,懶漢模式和餓漢模式 懶漢模式 class singleDemo...
摘要:文章系列設(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ì)模式--代理模式 概念...
摘要:什么是設(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ì)象。單例模式不僅能減少不必要...
閱讀 3029·2021-11-18 10:07
閱讀 3778·2021-11-17 17:00
閱讀 2108·2021-11-15 18:01
閱讀 936·2021-10-11 10:58
閱讀 3387·2021-09-10 10:50
閱讀 3453·2021-08-13 15:05
閱讀 1232·2019-08-30 15:53
閱讀 2657·2019-08-29 13:01