­

JS中的單例模式及單例模式原型類的實現

  • 2021 年 7 月 11 日
  • 筆記

單例模式

單例模式的定義: 保證一個類只有一個實例,並提供一個訪問它的全局訪問點

通過一個簡單的例子來了解單例模式的作用:

class Div {
    constructor() {
        return document.createElement("div");
    }
}

btn.addEventListener("click", function (event) {
    const div = new Div();
    document.body.appendChild(div);
});

現在頁面上的這個按鈕每被點擊一下就會生成一個div,但是現在如果這個div是登錄框,我當然就會想要這段函數只生成一個,這時候就可以用到單例模式的思想:讓一個類只會生成一個實例。

在JS里實現單例模式很簡單,只要使用閉包就能做到,這是使用ES6的class語法實現的單例模式:

let div = null;
class Div {
    constructor() {
        return div ?? (div = document.createElement("div"));
    }
}

這樣,通過閉包實現了單例模式,無論點擊多少次按鈕,只會生成一個div。

考慮到單例模式應用的廣泛,我實現了一個原型類,通過繼承該原型類可以直接得到一個單例模式的類:

const SingletonConstructor = (function () {
    const instances = {};
    return class {
        constructor(Constructor) {
            let className = new.target.name;
            if (instances[className]) {
                return instances[className];
            } else {
                let instance = new Constructor();
                Object.setPrototypeOf.call(null, instance, new.target.prototype);
                return (instances[className] = instance);
            }
        }
    };
})();

class Div extends SingletonConstructor {
    constructor() {
        super(function () {
            return document.createElement("div");
        });
    }
}

需要設計為單例的類只需要繼承這個原型類後在構造函數的super中寫入構造函數就能實現單例模式。