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

