js設(shè)計模式中單例模式的簡要說明
一. 認(rèn)識單例模式
單例模式的意思是,保證一個類只有一個實(shí)例,并且有一個接口供全局訪問。它的作用就是防止頻繁創(chuàng)建實(shí)例,浪費(fèi)不必要的內(nèi)存空間和資源消耗,那它有什么實(shí)用場景呢,假如我們在頁面中有一個點(diǎn)擊跳出一個彈窗操作,彈窗應(yīng)該是唯一的,無論點(diǎn)擊多少次它都應(yīng)該被構(gòu)建一次,那么這個彈窗就適合用單例模式來創(chuàng)建。
二. 單例模式的分類
- 簡單實(shí)現(xiàn)單例模式
- 透明實(shí)現(xiàn)單例模式
- 代理實(shí)現(xiàn)單例模式
- js單例模式
- 惰性單例模式
- 通用惰性單例模式(主要用于 js)
注: 前三種單例模式為用類實(shí)現(xiàn)的思想,通過 new 的方式來創(chuàng)建實(shí)例,而 javascript 是沒有類的,可以直接創(chuàng)建實(shí)例,因此并不適用,主要用于后邊三種。
三. 具體實(shí)現(xiàn)和思想學(xué)習(xí)
1. 簡單實(shí)現(xiàn)單例模式
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
實(shí)現(xiàn)思想:將第一次創(chuàng)建的實(shí)例進(jìn)行保存,之后再次創(chuàng)建前判斷是否已經(jīng)創(chuàng)建,如果之前創(chuàng)建過則返回已經(jīng)保存的實(shí)例,否則創(chuàng)建一個實(shí)例,將實(shí)例創(chuàng)建和判斷封裝到了一個 getInstance 函數(shù)中,這種方式相對簡單,但增加了類的“不透明性”,用一個函數(shù)來獲取一個實(shí)例,而不是以往通過 new 來創(chuàng)建。
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
實(shí)現(xiàn)思想:該方式與前一實(shí)現(xiàn)不同的在于用 new 來創(chuàng)建實(shí)例,運(yùn)用了閉包來保存實(shí)例標(biāo)識,從而達(dá)到只能創(chuàng)建唯一實(shí)例,但是如果有一天想創(chuàng)建多個 div 實(shí)例,該代碼就不實(shí)用了,必須修改代碼,因此擴(kuò)展除了代理實(shí)現(xiàn)。
3. 代理實(shí)現(xiàn)單例模式
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
實(shí)現(xiàn)思想:CreateDiv 為一個普通類,將創(chuàng)建和判斷唯一實(shí)例封裝在了代理函數(shù)中,增加了代碼復(fù)用性,彌補(bǔ)了透明單例的不足,需要單例則直接 new ProxySingletonCreateDiv(),需要普通實(shí)例則直接 new CreateDiv(),但是該方式代碼可讀性差,也不采用。
4. js的單例模式
① 使用命名空間來創(chuàng)建:將所有變量和方法直接放在一個全局對象中
let S = { name: '石頭山', getName() { console.log(this.name); } }
② 使用閉包封裝私有變量:將變量封裝在閉包內(nèi)部,只向全局暴露一個訪問接口
let name = "石頭山"; return { getName() { return name; } } }
5. 通用惰性單例
// 寫一個通用的獲取單例的函數(shù) , fn 為執(zhí)行單次的函數(shù) 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('我出現(xiàn)了') }); }(); // 無論渲染多少次,事件只綁定一次 let render = function () { console.log('開始渲染!'); getSingle(bindEvent) } render(); render(); render();
該方式是 js 中常用的單例實(shí)現(xiàn)方法,再頁面重復(fù)渲染三次時,監(jiān)聽事件只綁定了一次,減少了開銷。
惰性體現(xiàn):惰性體現(xiàn)在實(shí)例實(shí)在需要時創(chuàng)建,并不會在頁面加載好就創(chuàng)建。
實(shí)現(xiàn)思想:首先利用閉包和高階函數(shù)封裝了一個返回單一實(shí)例的函數(shù),其參數(shù)就是一個只執(zhí)行一次的函數(shù),可以隨時改變單例的作用,大大增加了代碼的可復(fù)用性。
四. 總結(jié)
單例模式是一種簡單但非常使用的開發(fā)模式,js 開發(fā)中,通用惰性單例實(shí)現(xiàn)方式最常用的一中方式,它將創(chuàng)建對象和管理單例的職責(zé)封裝在兩個不同的方法中,組合在一起就具有了單例模式的威力。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Javascript & DHTML 實(shí)例編程(教程)基礎(chǔ)知識
Javascript & DHTML 實(shí)例編程(教程)基礎(chǔ)知識...2007-06-06實(shí)例分析javascript中的call()和apply()方法
因項(xiàng)目需求去研究了下javascript中的call和apply方法,去百度看了幾篇介紹JS中call和apply的文章,總覺得不是很好懂,這里寫下我自己的理解,供網(wǎng)友們參考。2014-11-11JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡單方法
這篇文章主要介紹了JS阻止冒泡事件以及默認(rèn)事件發(fā)生的簡單方法,有需要的朋友可以參考一下2014-01-01