摘要:單例模式單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。透明的單例模式利用一個形成一個閉包,在里邊通過變量來記錄實例,并返回構造函數。
單例模式
單例模式,也叫單子模式,是一種常用的軟件設計模式。在應用這個模式時,單例對象的類必須保證只有一個實例存在。
———來自維基百科
一個很典型的應用是在點擊登錄按鈕,彈出登錄浮窗,不論點擊多少次登錄按鈕,頁面始終只會彈出一個登錄浮窗。
實現單例模式思路很簡單,用一個變量記錄是否已經為某個類創建過對象,如果沒有則返回新建的對象,反之則返回之前創建的對象。
在構造器里記錄實例: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使用閉包記錄實例:
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
以上方法相對簡單,但是Singleton類的使用者必須知道這是一個單例類,需要調用getInstance()函數(而不是new的方式)來獲取對象,這也就是增加了“不透明性”。
透明的單例模式利用一個IIFE形成一個閉包,在里邊通過變量instance來記錄實例,并返回構造函數。
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
上面完成了一個透明的單例類的編寫,但還是有缺點,增加了一些程序的復雜度,且閱讀性差。還有重要的一點是違反了“單一職責原則”,接下來再改進一下。
用代理實現單例模式其實就是將實際的業務代碼與負責管理單例的代碼分離,管理單例的類就是代理類。
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 // 如果想要創建多個 div 就直接調用 CreateDiv 咯 var a2 = new CreateDiv("sean1"); var b2 = new CreateDiv("sean2"); console.log(a2 === b2); // falseJavaScript 中的單例模式
前面提到的幾種實現,更多的是接近傳統面向對象語言中的實現,但 JavaScript 是一門無類(class-free)語言,我們只要記住單例模式但核心是 確保只有一個實例,并提供全局訪問。
全局變量不是單例模式,但它卻滿足單例的條件,所以我們經常會把全局變量當成單例來使用:var a = {};。但是我們都知道全局變量很容易造成命名空間污染、容易被不小心覆蓋等問題。我們有必要盡量減少全局變量的使用,即使要,也要將污染降到最低:
使用命名空間
var namespace1 = { a: function() { return 1; }, b: function() { return 2; } }; // 或者動態創建命名空間: 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; } }; })();惰性單例
所謂惰性,就是只有在需要的時候才會去做。前面提到的也有滿足惰性的實現,不過是基于“類”的。下面來看一下文章開頭提到的那個典型的應用實現:
上面的代碼完成了惰性單例的實現,但仍然違反了單一職責原則,如果我們下次不是創建一個登錄浮窗而是別的元素呢,請往后看通用的惰性單例。
通用的惰性單例// 定義一個管理單例的函數: 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("btn").onclick = function() { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block"; };參考
曾探. JavaScript設計模式與開發實踐 (圖靈原創) (Chinese Edition)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106810.html
摘要:文章系列設計模式單例模式設計模式策略模式設計模式代理模式概念單例模式的定義是保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。在開發中,單例模式的用途同樣非常廣泛。 前言 本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。 文章系列 js設計模式--單例模式 js設計模式--策略模式 js設計模式--代理模式 概念...
摘要:什么是設計模式設計模式是一種能夠被反復使用,符合面向對象特性的代碼設計經驗的總結,合理的使用設計模式能夠讓你得代碼更容易維護和可靠設計模式的類型共分為創建型模式,結構型模式,行為型模式三種創建型模式創建型模式是對一個類的實例化過程進行了抽象 什么是設計模式 設計模式是一種能夠被反復使用,符合面向對象特性的代碼設計經驗的總結,合理的使用設計模式能夠讓你得代碼更容易維護和可靠設計模式的類型...
摘要:什么是單例模式單例模式是一種十分常用但卻相對而言比較簡單的單例模式。對象就是單例模式的體現??偨Y單例模式雖然簡單,但是在項目中的應用場景卻是相當多的,單例模式的核心是確保只有一個實例,并提供全局訪問。 1. 什么是單例模式? 單例模式是一種十分常用但卻相對而言比較簡單的單例模式。它是指在一個類只能有一個實例,即使多次實例化該類,也只返回第一次實例化后的實例對象。單例模式不僅能減少不必要...
閱讀 3029·2021-11-18 10:07
閱讀 3777·2021-11-17 17:00
閱讀 2107·2021-11-15 18:01
閱讀 933·2021-10-11 10:58
閱讀 3383·2021-09-10 10:50
閱讀 3451·2021-08-13 15:05
閱讀 1232·2019-08-30 15:53
閱讀 2652·2019-08-29 13:01