單例模式的定義:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
例子1 用代理的方式實(shí)現(xiàn)單例模式
下面的代碼的功能是在頁面中創(chuàng)建一個(gè)div
var CreateDiv = function(html){
this.html = html;
this.init();
};
CreateDiv.prototype.init = function(){
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div);
};
// 代理類
var ProxyCreateDiv = (function(){
var instance;
return function(html){
if(!instance){
instance = new CreateDiv(html);
}
return instance;
}
})();
var a = new ProxyCreateDiv('div1');
var b = new ProxyCreateDiv('div2');
console.log(a === b); // true
惰性單例
var createLogin = (function(){
var div;
if(!div){
div = document.createElement('div');
div.innerHTML = '登錄框';
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
})();
document.getElementById('loginBtn').onclick = function(){
var loginLayer = createLogin();
loginLayer.style.display = 'block';
}
上面的代碼還存在一些問題,例如違反了單一職責(zé),如果我們下次需要?jiǎng)?chuàng)建的不是div,而是script或者iframe什么的,只能把createLogin重新復(fù)制一份出來
下面我們把管理單例的邏輯抽離出來,這些邏輯被單獨(dú)封裝在getSingle函數(shù)內(nèi)部,創(chuàng)建對(duì)象的方法fn被當(dāng)成參數(shù)動(dòng)態(tài)傳入getSingle函數(shù)
var getSingle = function(fn){
var result;
return function(){
return result || (result = fn.apply(this,arguments));
}
};
var createLogin = (function(){
div = document.createElement('div');
div.innerHTML = '登錄框';
div.style.display = 'none';
document.body.appendChild(div);
return div;
})();
var createSingleLogin = getSingle(createLogin);
document.getElementById('loginBtn').onclick = function(){
var loginLayer = createSingleLogin();
loginLayer.style.display = 'block';
}
//如果需要?jiǎng)?chuàng)建一個(gè)iframe 也是很方便的
var createSingleIframe = getSingle(function(){
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
return iframe;
});
document.getElementById('iframeBtn').onclick = function(){
var iframeLayer = createSingleIframe();
iframeLayer.src = 'http://www.xxx.com';
}
getSingle可以實(shí)現(xiàn)很多函數(shù)的單例效果