Javascript設計模式之單例模式

擼狗吸貓發表於2019-03-20

前言:菜雞也有夢想,而我的夢想就是進一個真正的網際網路大廠。以前學習的時候沒有系統的整理,從今天開始要保持每週寫部落格的習慣,希望自己可以有所成長。為了培養程式設計思維,決定從設計模式開始寫起。我是通過讀《Javascript設計模式與開發實踐》來學習設計模式,並且將知識點和收穫記錄在部落格中。

此文僅記錄本人閱讀《JavaScript設計模式與開發實踐》的知識點與想法,感謝作者曾探大大寫出這麼好的一本書。如有冒犯,請聯絡本人:markcoder@outlook.com處理,請大家購買正版書籍。

1. 單例模式介紹

單例模式的定義是:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點。

比如登入框和購物車就適合用單例模式。

2.程式碼實現

要點:用一個變數來標誌當前是否已經為某個類建立過物件,如果是,則在下一次獲取該類的例項時,直接返回之前建立的物件。

const Singleton = function (name) {
    this.name = name;
    this.instance = null;
};

Singleton.prototype.getName = function () {
    alert(this.name);
};

Singleton.getInstance = function (name) {
    if (!this.instance) { // 如果之前沒有建立過例項
        this.instance = new Singleton(name);
    }
    return this.instance;
};

let a = Singleton.getInstance('event1');
let b = Singleton.getInstance('event2');

console.log(a === b); // true
複製程式碼

或者

const Singleton = function (name) {
    this.name = name;
};

Singleton.prototype.getName = function () {
    alert(this.name);
};

Singleton.getInstance = (function () {
    let instance = null;
    return function (name) {
        if (!instance) { // 如果之前沒有建立過例項
            instance = new Singleton(name);
        }
        return instance;
    }
})();

let a = Singleton.getInstance('event1');
let b = Singleton.getInstance('event2');

console.log(a === b); // true
複製程式碼

ES6實現

class Singleton {
    login () {
        console.log(login)
    }
}

Singleton.getInstance = (function () {
    let instance;
    return function () {
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    }
})();

let a = Singleton.getInstance();
let b = Singleton.getInstance();

console.log(a === b); // true
複製程式碼

Singleton類的使用者必須知道通過 Singleton.getInstance 這個方法來獲取物件,而不是通過 new XXX 的方式。

3.透明的單例模式

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 div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild(div);
    };
    
    return CreateDiv; // 返回真正的構造方法
    
})();

let a = new CreateDiv( 'event1' ); 
let b = new CreateDiv( 'event2' ); 

console.log ( a === b ); // true 
複製程式碼

通過匿名函式返回真正的建構函式 CreateDiv 。假如某天我們要在頁面中建立更多的div,就需要修改建構函式,所以程式碼仍然需要改進。

4.用代理實現單例模式

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);
};

// 利用閉包將管理單例模式的邏輯放在了proxySingleton
let proxySingleton = (function () {
    var instance;
    return function (html) {
        if (!instance) {
            instance = new CreateDiv(html);
        }
        return instance;
    }
})();

let a = new proxySingleton( 'sven1' ); 
let b = new proxySingleton( 'sven2' ); 
console.log ( a === b ); 
複製程式碼

5.使用單例模式的總結

  • 模擬登入框
class Login {
    constructor () {
        this.state = 'hide'
    }
    
    show () {
        if (this.state === 'show') {
            return    
        }    
        this.state = 'show'
    }
    
    hide () {
        if (this.state === 'hide') {
            return
        }
        this.state = 'hide'
    }
}

Login.getInstance = (function () {
    let instance;
    return function () {
         if (!instance) {
            instance = new Login();
        }
        return instance   
    }
})();

let login1 = Login.getInstance();
let login2 = Login.getInstance();

console.log(login1 === login2);
複製程式碼
  • 無論引入多少次jQuery庫,全域性只有一個$
if (window.jQuery != null) {
    return window.jQuery
} else {
    // 初始化
}
複製程式碼
  • vuex和redux的store

參考

《JavaScript設計模式與開發實踐》—— 曾探

相關文章