單例模式的定義是:保證一個(gè)類僅有一個(gè)實(shí)例朝氓,并提供一個(gè)訪問它的全局訪問點(diǎn)径荔。
單例模式是一種常用的模式,有一些對象我們往往只需要?jiǎng)?chuàng)建一個(gè)颠黎,比如線程池另锋,全局緩存,瀏覽器中的window對象等狭归。在JS開發(fā)中夭坪,單例模式的用途同樣非常廣泛,比如當(dāng)我們單擊一個(gè)登陸按鈕的時(shí)候过椎,頁面會(huì)浮現(xiàn)一個(gè)登陸窗口室梅,而且這個(gè)窗口是唯一的,無論點(diǎn)擊多少次登陸按鈕疚宇,這個(gè)窗口只會(huì)被創(chuàng)建一次亡鼠,那么這個(gè)窗口就適合用單例模式來創(chuàng)建。
首先我們先實(shí)現(xiàn)一個(gè)“透明”的單例類敷待,使用CreateDiv單例類间涵,它的作用是負(fù)責(zé)在頁面中創(chuàng)建唯一的DIV節(jié)點(diǎn),代碼如下:
varCreatDiv=(function(){
varinstance;
varCreateDiv=function(html){
if(instance){
returninstance
}
this.html=html;
this.init();
returninstance=this;
};
CreateDiv.prototype.innit=function(){
vardiv=document.createElement('div');
div.innerHTML=this.html;
document.body.appendChild(div);
};
returnCreateDiv;
})();
vara=newCreatDiv('Tom');
varb=newCreatDiv('Jack');
alert(a==b);//true
通過上面這個(gè)例子榜揖,我們可以能看出勾哩,單例模式的大體思想就是先判斷這個(gè)例子是否存在。轉(zhuǎn)換成代碼就是下面這個(gè)意思:
var obj;
if(!obj){
obj=xxx;
}
現(xiàn)在我們了解了一些單例模式的實(shí)現(xiàn)方法举哟,接下來我們再看惰性單例思劳。惰性單例指的是在需要的時(shí)候才創(chuàng)建對象實(shí)例,惰性單例是單例模式的重點(diǎn)妨猩。就那剛才那個(gè)登陸窗口來說潜叛,其實(shí)用戶只是單純?yōu)g覽網(wǎng)站時(shí)候,其實(shí)不需要進(jìn)行登陸册赛。按照我自己之前的開發(fā)方式钠导,就是在頁面初始化的時(shí)候就創(chuàng)建了這么一個(gè)窗口,再將它display為none森瘪。學(xué)習(xí)了單例模式后牡属,發(fā)現(xiàn)有更好的辦法,那就是惰性單例:只有當(dāng)用戶點(diǎn)擊登陸時(shí)候我才開始創(chuàng)建并顯示這個(gè)窗口扼睬,然后當(dāng)用戶多次點(diǎn)擊登陸時(shí)候逮栅,其實(shí)顯示的是同一個(gè)登陸窗口悴势。
另外,我們把創(chuàng)建實(shí)例對象的職責(zé)和管理單例的職責(zé)分別放在兩個(gè)方法里措伐,這兩個(gè)方法可以獨(dú)立變化而互不影響特纤,當(dāng)它們連接在一起的時(shí)候,就完成了創(chuàng)建唯一實(shí)例對象的功能侥加。這樣的做法體現(xiàn)了單一職責(zé)原則捧存。上代碼,哈哈
vargetSingle=function(fn){
varresult;
return function(){
returnresult||(result=fn.apply(this,arguments));
}
};
varcreateLoginLayer=function(){
vardiv=document.createElement('div');
div.innerHTML='我是登錄框';
div.style.display='none';
document.body.appendChild(div);
returndiv;
};
varcreatSingleLoginLayer=getSingle(createLoginLayer);
//假設(shè)【登陸】按鈕的id是loginBtn
document.getElementById('loginBtn').onclick=function(){
varloginLayer=creatSingleLoginLayer();
loginLayer.style.display='none';
};