单例模式确保一个类只有一个实例并提供全局访问点,核心是控制创建时机、防止重复初始化、保证多次调用返回同一对象;常用实现包括闭包缓存、ES6 class 静态属性及惰性安全的私有静态属性方式。
JavaScript 中常用的设计模式包括单例模式、工厂模式、观察者模式(发布-订阅)、策略模式、代理模式、装饰器模式、适配器模式、命令模式、状态模式等。其中单例模式最常用于管理全局唯一实例,比如配置管理器、日志记录器、弹窗控制器等。
单例模式确保一个类只有一个
实例,并提供一个全局访问点。关键在于:控制实例的创建时机、防止重复初始化、保证多次调用返回同一对象。
这是最简洁、易理解的方式,利用立即执行函数封装私有变量,避免污染全局作用域:
const Singleton = (function() {
let instance = null;
function createInstance() {
return {
name: 'Singleton Instance',
getId: () => Math.random().toString(36).substr(2, 9)
};
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
// 使用
const a = Singleton.getInstance();
const b = Singleton.getInstance();
console.log(a === b); // true
借助 class 语法和静态属性,语义更清晰,也便于扩展:
class Logger {
constructor() {
if (Logger.instance) {
return Logger.instance;
}
this.logs = [];
Logger.instance = this;
}
log(message) {
this.logs.push([${new Date().toISOString()}] ${message});
}
getLogCount() {
return this.logs.length;
}
}
// 手动初始化一次(或在首次调用时惰性初始化)
Logger.instance = null;
// 使用
const logger1 = new Logger();
const logger2 = new Logger();
console.log(logger1 === logger2); // true
把实例创建逻辑完全封装在类内部,外部无需关心初始化细节:
class DatabaseConnection {
static #instance = null;
constructor() {
if (DatabaseConnection.#instance) {
return DatabaseConnection.#instance;
}
this.connectionId = conn_${Date.now()}_${Math.random().toFixed(4)};
DatabaseConnection.#instance = this;
}
static getInstance() {
if (!DatabaseConnection.#instance) {
DatabaseConnection.#instance = new DatabaseConnection();
}
return DatabaseConnection.#instance;
}
query(sql) {
console.log(Executing: ${sql} on ${this.connectionId});
}
}
// 使用
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();
console.log(db1 === db2); // true
db1.query('SELECT * FROM users');
不复杂但容易忽略