單例模式
簡單的單例模式
通過一個getInstance方法獲取物件,首先判斷一個物件是否存在,如果存在則就將改物件回傳,如果不存在就先實體化物件(創建物件),然后再回傳
將實體存盤在物件中
let Singleton = function(name){
this.name = name;
}
// 將實體存盤在物件中
Singleton.getInstance = function() {
// 如果本身到
if(this.instance === null){
this.instance = new Singleton();
}
return this.instance;
}
let aIns = Singleton.getInstance("test");
let bIns = Singleton.getInstance("test");
console.log(aIns === bIns);
使用閉包存盤實體物件
// 將實體使用閉包的形式存盤起來
Singleton.getInstanceNew = (function() {
let instance = null;
return function(){
if(instance === null){
instance = new Singleton();
}
return instance;
}
}())
let cIns = Singleton.getInstanceNew("test");
let dIns = Singleton.getInstanceNew("test");
console.log(cIns === dIns, aIns === dIns);
我們看到以上兩個方法,都是創建單例的簡單方法,雖然實作了,但是如果別人不知道這個物件時單例的,還是可以使用
new關鍵字創建,并且不再是單例了,所以很容易違背了我們單例的初心
透明的單例模式
我們依然通過new創建實體,但是創建的還是單例的,這樣即使不需要我們特意去囑咐這個物件是單例
var TransparentSingleton = (function() {
var instance = null;
var TransparentSingleton = function(){
if(instance){
return instance;
}
this.init();
return instance = this;
}
TransparentSingleton.prototype.init = function(){
console.log("Dom操作")
}
return TransparentSingleton;
}())
let eIns = new TransparentSingleton();
let fIns = new TransparentSingleton();
console.log(eIns === fIns);
這種方法雖然滿足了我們的要求,但是這里存在一個問題,就是內部的
TransparentSingleton的這物件,成為了一個私有物件,我們在外面無法訪問到
代理版單例模式
var CreateDom = function(html){
this.html = html;
this.init();
}
CreateDom.prototype.init = function(){
console.log(this.html);
}
var ProxyCreateDom = (function(){
let instance = null;
return function(html){
if(instance === null){
instance = new CreateDom(html);
}
return instance;
}
}())
let hIns = new ProxyCreateDom("測驗");
let gIns = new ProxyCreateDom("前端");
console.log(hIns === gIns, hIns.html, gIns.html)
這里我們將物件提了出來了,通過
ProxyCreateDom去創建一個關于CreateDom的單例,但是這個版本是比較有限的,我們可以看到這個代理單例并不是一個可復用的,代碼很可能會翻倍,并且不管我們需不要單例,其實ProxyCreateDom里的instance就創建了,并且這個是屬于傳統面向物件語言的,在JavaScript這個沒有類的語言中,這樣創建意義并不大
惰性單例模式通用版本
let getSingleton = function(func) {
let result = null;
return function(){
return result || (result = func.apply(this, arguments));
}
}
function createLoginLayer(){
var div = document.createElement("div");
div.innerHTML = "我是登錄浮窗";
div.style.display = "none";
document.body.appendChild(div);
return div;
}
/**
* 測驗代碼
*/
let createSingleLoginLayer = getSingleton(createLoginLayer);
// 添加一個登陸浮窗
document.getElementById("loginTest").onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "block"
}
// 創建一個iframe的單例
var createSingleIfame = getSingleton(function () {
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
return iframe;
})
// 創建一個iframe,并將src屬性設定為百度
document.getElementById("loginBtn").onclick = function(){
var loginLayer = createSingleIfame();
loginLayer.src = "http://baidu,com";
}
// 將浮窗單例隱藏
document.getElementById("closeLoginBtn").onclick = function(){
var loginLayer = createSingleLoginLayer();
loginLayer.style.display = "none"
}
// 改變iframe的src屬性
document.getElementById("changeUrlBtn").onclick = function(){
var loginLayer = createSingleIfame();
loginLayer.src = "http://127.0.0.1:5500/index.html";
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/259946.html
標籤:JavaScript
上一篇:【原】無腦操作:Centos 7.6 + MariaDB + Rsyslog + LogAnalyzer環境搭建
下一篇:JavaScript函式
