定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用场景
一个单一对象。比如页面中有一个登陆按钮,点击后出现一个登陆弹窗,而这个弹窗是唯一的,不管按钮点击几次,弹框只会被创建一次,那这个弹窗就适合单例模式来创建。
模式实现
以上述应用场景为例
const createLoginModal = (function() {
let div;
return function() {
if (div) return div;
div = document.createElement("div");
div.innerHTML = "我是弹窗";
div.style.display = "none";
document.body.appendChild(div);
};
})();
document.getElementById("loginBtn").onclick = () => {
const loginModal = createLoginModal();
loginModal.style.display = "block";
};
通用的单例
上面实现了一个可用的单例方法,但是没法通用。如果想再创建一个span标签的话,几乎要把createLoginModal照抄一遍。
我们需要把不变的部分(管理单例的逻辑)抽离出来,把创建对象的方法通过 fn 当成参数动态传入getSingle函数:
function getSingle (fn) {
let result
return function() {
if (result) return result
result = fn.apply(this, arguments)
return result
}
接下来用来创建弹窗的方法可以用参数fn的形式传入getSingle。代码如下:
const createLoginModal = function() {
const div = document.createElement("div");
div.innerHTML = "我是弹窗";
div.style.display = "none";
document.body.appendChild(div);
return div;
};
const createSingleLoginModal = getSingle(createLoginModal);
document.getElementById("loginBtn").onclick = () => {
const loginModal = createSingleLoginModal();
loginModal.style.display = "block";
};
单例模式适用性
- 如果程序中的某个类对于所有客户端只有一个可用的实例,可以使用单例模式。
单例模式禁止通过除了特殊构建方法以外的任何方式来创建自身类对象。 该方法可以创建一个新对象,但如果该对象已经被创建,则返回已有的对象。
- 如果你需要更加严格地控制全局变量,可以使用单例模式。
单例模式与全局变量不同,它保证类只存在一个实例。 除了单例类自己以外,无法通过任何方式替换缓存的实例。
参考
- 《深入设计模式》
- 《JavaScript 设计模式与开发实践》