Skip to main content

创建型 | 单例模式

单例模式是最简单的设计模式之一。

意图#

保证一个类仅有一个实例, 并提供一个访问该实例的全局节点。

场景#

  • 程序中的某个类对于所有客户端仅有一个可用的实例
  • 更加严苛地控制全局变量

应用:

  • 线程池
  • 全局缓存
  • 浏览器中的window对象

缺点#

  • 违反单一职责原则

实现#

// 1. 创建一个 Singleton 类
class SingleObject {
//创建 SingleObject 的一个对象
private static instance: SingleObject = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
constructor() { }
//获取唯一可用的对象
public static getInstance(): SingleObject {
return this.instance;
}
public showMessage(): void {
console.log("Hello World!");
}
}

测试

// 2. 从 singleton 类获取唯一的对象
class SingletonPatternDemo {
constructor() {
//获取唯一可用的对象
let object: SingleObject = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
new SingletonPatternDemo();
// Hello World!

案例: 弹窗#

通过闭包存储实例,并进行判断,不管点击登录按钮多少次,只创建一个登录浮窗实例

⚠️ 销毁组件前清除闭包

<button id="clickBtn">测试按钮</button>
<script>
let createSingle = (function () {
let instance = {};
return function (fn) {
if (!instance[fn.name]) {
instance[fn.name] = fn.apply(this, arguments);
}
return instance[fn.name]
}
})();
function createAdd () {
const el = document.createElement('div');
el.innerHTML = '新增';
el.style.display = 'none';
document.body.appendChild(el);
return el;
}
function createEdit () {
const el = document.createElement('div');
el.innerHTML = '编辑';
el.style.display = 'none';
document.body.appendChild(el);
return el;
}
document.getElementById('clickBtn').onclick = () => {
let add = createSingle(createAdd);
let edit = createSingle(createEdit);
add.style.display = 'block';
edit.style.display = 'block';
}
</script>