摘要:本系列為設計模式與開發實踐作者曾探學習總結,如想深入了解,請支持作者原版單例模式實現單例模式單例模式的定義是保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
本系列為《JavaScript設計模式與開發實踐》(作者:曾探)學習總結,如想深入了解,請支持作者原版
單例模式 實現單例模式單例模式的定義是:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。
單例模式是一種常用的模式,有一些對象我們往往只需要一個,比如登錄窗口,這個窗口是唯一的,無論我們點擊多少次登錄按鈕,這個窗口只會被創建一次,那么這個窗口就適合用單例模式來創建。
要實現一個標準的單例模式并不復雜,無非是用一個變量來標志當前是否已經為某個類創建過對象,如果是,則在下一次獲取該類的實例時,直接返回之前創建的對象。代碼如下:
var Singleton=function(name){ this.name=name; this.instance=null; }; Singleton.prototype.getName=function(){ alert(this.name); }; Singleton.getInstance=function(){ if(!this.instance){ this.instance=new Singleton(name); } return this.instance; }; var a=Singleton.getInstance("sven1"); var b=Singleton.getInstance("sven2"); alert(a===b);//true
或者
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; } })();
我們通過Singleton.getInstance來獲取Singleton類的唯一對象,這種方式相對簡單,但是不透明。跟以往通過new XXX的方式獲取對象不同,這里偏要使用Singleton.getInstance來獲取對象,所以這段代碼的意義并不大。
透明的單例模式我們現在的目標是實現一個透明的單例類。
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("sven1"); var b = new CreateDiv("sven2"); alert(a===b);//true
雖然現在完成了一個透明的單例類的編寫,但它同樣有一些缺點。為了把instance封裝起來,我們使用了自執行的匿名函數和閉包,并且讓這個匿名函數返回真正的Singleton構造方法,這增加了一些程序的復雜度,閱讀起來也不是很舒服。
假設我們某天需要讓這個單例類變成一個普通的類,即可以產生多個實例,那我們必須改寫CreateDiv構造函數,這種修改會帶來很多不必要的麻煩。
我們首先創建一個普通的CreateDiv類:
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); };
接下來引入代理類ProxySingletonCreate:
var ProxySingletonCreate = (function() { var instance; return function(html) { if (!instance) { instance = new CreateDiv(html); } return instance; } })(); var a = new ProxySingletonCreate("sven1"); var b = new ProxySingletonCreate("sven2"); console.log(a === b);
這樣一來,CreateDiv和ProxySingletonCreate組合起來,實現了單例模式的效果。
JavaScript中的單例模式前面提到的幾種單例模式的實現,更多的是接近傳統面向對象語言中的實現,單例對象從類中創建而來。但JavaScript其實是一門無類的語言,所以生搬單例模式的概念并無意義。
單例模式的核心是:確保只有一個實例,并提供全局訪問。
全局變量不是單例模式,但在實際應用中,我們經常會把全局變量當成單例來使用。
例如:
var a = {};
全局變量可以滿足上述的兩個條件,但卻存在許多問題:它很容易造成命名空間污染。作為普通的開發者,我們有必要減少全局變量的使用,一下幾種方式可以相對降低全局變量帶來的命名污染。
使用命名空間最簡單的方法依然是使用對象字面量方式:
var namespace1={ a:function(){ }, b:function(){ } };
我們還可以動態的創建命名空間:
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.log(myApp);使用閉包封裝私有變量
var user=(function(){ var _name="sven",_age=29; return { getUserInfo:function(){ return _name+"_"+_age; } } })();惰性單例
惰性單例指的是在需要的時候才創建對象實例。惰性單例是單例模式的重點,這種技術在實際開發中非常有用。
我們先抽取出一個管理單例的邏輯對象:
var getSingle=function(fn){ var result; return function(){ return result||(result=fn.apply(this.arguments)); } };
創建對象的方法fn被當做參數傳入getSingle。
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.width = "100px"; div.style.height = "100px"; div.style.background = "red"; document.body.appendChild(div); return div; }; aa = getSingle(createLoginLayer); aa();
result變量因為身在閉包中,永遠不會被銷毀。在將來的請求中,如果result已經被賦值,那么他將返回這個值。
以下是演示地址:
惰性單例演示地址
其他演示地址
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78844.html
摘要:所以程序在引入文件的時候用了單例模式,一個文件實例化一次,這種做法無疑是好的,但是也容易引起。在我們平時的開發過程中,可以借鑒這兩種方式去緩存變量,節點等。 這一章作者講了一個例子,就是在用單例模式生成一個dom節點,還要做到只有訪問的時候才創建,后續訪問直接用前面創建的。那么實際開發中我們會用到這個模式嗎?現在我們基本都是用vue,react,angular開發,不太會直接去操作do...
摘要:大潮來襲前端開發能做些什么去年谷歌和火狐針對提出了的標準,顧名思義,即的體驗方式,我們可以戴著頭顯享受沉浸式的網頁,新的標準讓我們可以使用語言來開發。 VR 大潮來襲 --- 前端開發能做些什么 去年谷歌和火狐針對 WebVR 提出了 WebVR API 的標準,顧名思義,WebVR 即 web + VR 的體驗方式,我們可以戴著頭顯享受沉浸式的網頁,新的 API 標準讓我們可以使用 ...
閱讀 3658·2021-11-15 11:37
閱讀 2317·2021-09-24 10:39
閱讀 2443·2021-07-25 21:37
閱讀 1429·2019-08-30 15:56
閱讀 2580·2019-08-30 15:55
閱讀 948·2019-08-30 15:54
閱讀 2122·2019-08-30 14:21
閱讀 853·2019-08-30 11:24