單例模式之es3與es6雙版本(設計模式)

定義

保證一個類僅有以一個實例,僅能被實例化/建立一次,並提供全局的訪問點。javascript

單例模式是一種重要的設計模式,有些對象咱們只須要建立一個,好比瀏覽器的window對象,模態對話框。實現這種設計模式其實很簡單,最重要的是在建立實例的時候,用一個標記變量判斷實例是否已經建立。html

普通青年寫法

function Singleton(name){
    this.name = name;
    this.instance = null;
}
Singleton.prototype.getName = function(){
    console.log('name: ' + this.name);
    return this.name;
}
Singleton.getInstance = function(name){
    if(!this.instance){
        this.instance = new Singleton(name);
    }
    return this.instance;
}
var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
alert(a === b);

點評:
該寫法不透明,使用者必須知道用Singleton.getInstance獲取單例,而非經過更加通用的方法new xxx方式。java

老司機寫法

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 SingletonDiv = (function(){
    var instance;
    return function(html){
        if(!instance){
            instance = new CreateDiv(html);
        }
        return instance;
    }
})()
var a = SingletonDiv('yyh');
var b = SingletonDiv('yyh1');

點評:
使用代理類+普通的類,使得職責分明。普通類負責實現基本功能,代理類管理單例。CreateDiv能夠直接生產一個實例,而加上代理,能夠實現單例。有木有一種模塊拼湊的快感,這就實現了低耦合。設計模式

華麗麗的ES6

在ES6中,能夠使用static方法代替閉包存儲單例。瀏覽器

靜態方法的單例模式

class Singleton {
    constructor(name) {
        this.name = name;
    }
    static getInstance(name) {
        if(!Singleton.instance) {
            Singleton.instance = new Singleton(name)
        }
        return Singleton.instance;
    }
    getName() {
        return this.name;
    }
}
const singletonA = Singleton.getInstance('yyh1');
const singletonB = Singleton.getInstance('yyh2');
console.log(singletonA === singletonB);
console.log(singletonA.getName() === singletonB.getName());

點評:ES6的靜態方法,和閉包同樣能在減小全局變量污染的同時,使標記變量更加長久的保存在內存中不被回收。閉包

老司機的新技能(更加通用的實現方式)

// 負責建立DIV的基本功能
class CreateDiv {
    constructor(html) {
        this.html = html;
        this.init();
    }
    init() {
        const div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild(div);
    }
}
// 負責管理單例
class ProxysingletonCreateDiv {
    constructor(htmlStr) {
        return ProxysingletonCreateDiv.getInstance(htmlStr);
    }
    static getInstance(name) {
        if(!ProxysingletonCreateDiv.instance) {
            ProxysingletonCreateDiv.instance = new CreateDiv(name)
        }
        return ProxysingletonCreateDiv.instance;
    }
}
const singletonC = new ProxysingletonCreateDiv('yyh1');
const singletonD = new ProxysingletonCreateDiv('yyh2');
console.log(singletonC === singletonD);
singletonC.init();
singletonD.init();
相關文章
相關標籤/搜索