JavaScript程式設計的單例設計模講解_基礎知識
在Javascript中,單例模式是一種最基本又常用到的設計模式,可能在不經意間就用到了單例模式。
本文將從最基礎的理論開始,講述單例模式的基本概念和實現,最後用一個例子來講述單例模式的應用。
理論基礎
概念
單例模式,顧名思義就是只有一個實例存在。透過單例模式可以確保系統中一個類別只有一個實例而且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。如果希望在系統中某個類別的物件只能存在一個,單例模式是最好的解決方案。
基本結構
最簡單的單例模式起始就是一個物件字面量,它將有關聯的屬性和方法組織在一起。
var singleton = { prop:"value", method:function(){ } }
這種形式的單例模式,所有成員都是公開的,都可以透過singleton來存取。這樣的缺點是單例中有一些輔助的方法並不希望暴露給使用者,如果使用者用了這些方法,然後在後面維護的時候,一些輔助方法被刪除,這樣會造成程序錯誤。
如何避免這樣從的錯誤呢?
包含私有成員的單例模式
怎麼在類別中創建私有成員呢,這透過需要閉包來進行實現,關於閉包的知識,本文不再贅述,大家可以自行Google。
基本形式如下:
var singleton = (function () { var privateVar = "private"; return { prop: "value", method: function () { console.log(privateVar); } } })();
首先是一個自執行的匿名函數,在匿名函數中,宣告了一個變數privateVar,並傳回一個物件賦值給單例物件singleton。在匿名函數外部無法存取到privateVar變量,它就是單例物件的私有變量,只能在函數內部或透過暴露出來的方法去存取這個私有變數。這種形式又被成為模組模式。
惰性實例化
不管是直接字面量或私有成員的單例模式,兩者都是在腳本加載時就被創建出來的單例,但是有時候,頁面可能永遠也用不到這個單例對象,這樣會造成資源浪費。對於這種情況,最佳的處理方式就是惰性加載,就是說在需要的時候才去真正實例化這個單例對象,如何實現呢?
var singleton = (function () { function init() { var privateVar = "private"; return { prop: "value", method: function () { console.log(privateVar); } } } var instance = null; return { getInstance: function () { if (!instance) { instance = init(); } return instance; } } })();
先將建立單例物件的程式碼封裝到init函數中,然後宣告一個私有變數instance表示單例物件的實例,公開一個方法getInstance來取得單例物件。
調用的時候就透過singleton.getInstance()來進行調用,單例物件是在調用getInstance的時候才真正被創建。
適用場合
單例模式是JS中最常使用的設計模式,從增強模組性和程式碼組織性等方面來說,應該盡可能的使用單例模式。它可以把相關程式碼組織到一起方便維護,對於大型項目,每個模組惰性載入可以提高效能,隱藏實作細節,暴露出常用的api。常見的類別函式庫例如underscore,jQuery我們都可以將其理解為單例模式的應用。
結合實戰
前面已經講過,單例模式是最常用的設計模式之一,我們來舉個例子進行說明,
下面的程式碼主要實作一個簡單的日期幫助類,透過單例模式實現:
基本的單例模式結構
var dateTimeHelper = { now: function () { return new Date(); }, format: function (date) { return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); } }; console.log(dateTimeHelper.now());<br />
這段程式碼透過物件字面量實現單例模式,使用的時候直接呼叫方法即可。
惰性載入實作單例模式
var dateTimeHelper = (function () { function init() { return { now: function () { return new Date(); }, format: function (date) { return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); } } } var instance = null; return { getInstance: function () { if (!instance) { instance = init(); } return instance; } } })(); console.log(dateTimeHelper.getInstance().now())
這就是惰性載入的單例模式。
下面再來看幾個實例:
實現1: 最簡單的物件字面量
var singleton = { attr : 1, method : function(){ return this.attr; } } var t1 = singleton ; var t2 = singleton ;
那麼很明顯的, t1 === t2 。
十分簡單,而且非常使用,缺點在於沒有什麼封裝性,所有的屬性方法都是暴露的。對於一些需要使用私有變數的情況就顯得心有餘而力不足了。當然在對於 this 的問題上也是有一定弊端的。
實現2:建構子內部判斷
其實和最初的JS實作有點類似,不過是將對是否已經存在該類別的實例的判斷放入建構函數內部。
function Construct(){ // 确保只有单例 if( Construct.unique !== undefined ){ return Construct.unique; } // 其他代码 this.name = "NYF"; this.age="24"; Construct.unique = this; } var t1 = new Construct() ; var t2 = new Construct() ;
那么也有的, t1 === t2 。
也是非常简单,无非就是提出一个属性来做判断,但是该方式也没有安全性,一旦我在外部修改了Construct的unique属性,那么单例模式也就被破坏了。
实现3 : 闭包方式
对于大着 灵活 牌子的JS来说,任何问题都能找到 n 种答案,只不过让我自己去掂量孰优孰劣而已,下面就简单的举几个使用闭包实现单例模式的方法,无非也就是将创建了的单例缓存而已。
var single = (function(){ var unique; function Construct(){ // ... 生成单例的构造函数的代码 } unique = new Constuct(); return unique; })();
只要 每次讲 var t1 = single; var t2 = single;即可。 与对象字面量方式类似。不过相对而言更安全一点,当然也不是绝对安全。
如果希望会用调用 single() 方式来使用,那么也只需要将内部的 return 改为
return function(){ return unique; }
以上方式也可以使用 new 的方式来进行(形式主义的赶脚)。当然这边只是给了闭包的一种例子而已,也可以在 Construct 中判断单例是否存在 等等。 各种方式在各个不同情况做好选着即可。
总结
单例模式的好处在于对代码的组织作用,将相关的属性和方法封装在一个不会被多次实例化的对象中,让代码的维护和调试更加轻松。隐藏了实现细节,可以防止被错误修改,还防止了全局命名空间的污染。另外可以通过惰性加载提高性能,减少不必要的内存消耗。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
