js設計模式中單例模式的簡要說明
一. 認識單例模式
單例模式的意思是,保證一個類隻有一個實例,並且有一個接口供全局訪問。它的作用就是防止頻繁創建實例,浪費不必要的內存空間和資源消耗,那它有什麼實用場景呢,假如我們在頁面中有一個點擊跳出一個彈窗操作,彈窗應該是唯一的,無論點擊多少次它都應該被構建一次,那麼這個彈窗就適合用單例模式來創建。
二. 單例模式的分類
簡單實現單例模式透明實現單例模式代理實現單例模式js單例模式惰性單例模式通用惰性單例模式(主要用於 js)
註: 前三種單例模式為用類實現的思想,通過 new 的方式來創建實例,而 javascript 是沒有類的,可以直接創建實例,因此並不適用,主要用於後邊三種。
三. 具體實現和思想學習
1. 簡單實現單例模式
let Singleton = function ( name ) { this.name = name; } Singleton.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; } let a = Singleton.getInstance('sk'); let b = Singleton.getInstance('ss'); console.log(a); console.log(a === b) // true
實現思想:將第一次創建的實例進行保存,之後再次創建前判斷是否已經創建,如果之前創建過則返回已經保存的實例,否則創建一個實例,將實例創建和判斷封裝到瞭一個 getInstance 函數中,這種方式相對簡單,但增加瞭類的“不透明性”,用一個函數來獲取一個實例,而不是以往通過 new 來創建。
2. 透明單例模式
let CreateDiv = function () { let instance ; let CreateDiv = function ( html ) { if( instance ) { return instance; } this.html = html; this.init(); return instance = this; } CreateDiv.prototype.init = function () { let element = document.createElement('div'); element.innerHTML = this.html; document.body.appendChild(element); } return CreateDiv; }(); let a = new CreateDiv('石頭山'); let b = new CreateDiv('哈哈'); console.log(a === b); // true
實現思想:該方式與前一實現不同的在於用 new 來創建實例,運用瞭閉包來保存實例標識,從而達到隻能創建唯一實例,但是如果有一天想創建多個 div 實例,該代碼就不實用瞭,必須修改代碼,因此擴展除瞭代理實現。
3. 代理實現單例模式
let CreateDiv = function ( html ) { this.html = html; this.init(); } CreateDiv.prototype.init = function () { let div = document.createElement('div'); div.innerHTML = this.html; document.body.appendChild(div); } let ProxySingletonCreateDiv = function () { let instance ; return function ( html ) { if( !instance ) { instance = new CreateDiv( html ); } return instance; } }(); let a = new ProxySingletonCreateDiv('sven1'); let b = new ProxySingletonCreateDiv('sven2'); console.log(a === b); // true
實現思想:CreateDiv 為一個普通類,將創建和判斷唯一實例封裝在瞭代理函數中,增加瞭代碼復用性,彌補瞭透明單例的不足,需要單例則直接 new ProxySingletonCreateDiv(),需要普通實例則直接 new CreateDiv(),但是該方式代碼可讀性差,也不采用。
4. js的單例模式
① 使用命名空間來創建:將所有變量和方法直接放在一個全局對象中
let S = { name: '石頭山', getName() { console.log(this.name); } }
② 使用閉包封裝私有變量:將變量封裝在閉包內部,隻向全局暴露一個訪問接口
let name = "石頭山"; return { getName() { return name; } } }
5. 通用惰性單例
// 寫一個通用的獲取單例的函數 , fn 為執行單次的函數 let getSingle = function ( fn ) { let result; return function () { return result || ( result = fn.apply(this, arguments)) } } // 綁定事件 let bindEvent = function () { document.getElementById('div').addEventListener('click',()=>{ console.log('我出現瞭') }); }(); // 無論渲染多少次,事件隻綁定一次 let render = function () { console.log('開始渲染!'); getSingle(bindEvent) } render(); render(); render();
該方式是 js 中常用的單例實現方法,再頁面重復渲染三次時,監聽事件隻綁定瞭一次,減少瞭開銷。
惰性體現:惰性體現在實例實在需要時創建,並不會在頁面加載好就創建。
實現思想:首先利用閉包和高階函數封裝瞭一個返回單一實例的函數,其參數就是一個隻執行一次的函數,可以隨時改變單例的作用,大大增加瞭代碼的可復用性。
四. 總結
單例模式是一種簡單但非常使用的開發模式,js 開發中,通用惰性單例實現方式最常用的一中方式,它將創建對象和管理單例的職責封裝在兩個不同的方法中,組合在一起就具有瞭單例模式的威力。
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- 解析Javascript設計模式Revealing Module 揭示模式單例模式
- Java設計模式之單件模式深入講解
- c# 單例模式的實現
- 全面解析js中的原型,原型對象,原型鏈
- C++設計模式之單例模式詳解