单例模式的意义
单例模式(Singleton Pattern)是一种设计模式,其核心思想是确保一个类仅有一个实例,并提供全局访问点。它的意义包括:
- 资源优化:避免重复创建对象,节省内存和计算资源。
- 数据一致性:全局共享同一个实例,避免多实例导致状态不一致。
- 集中管理:适用于全局状态、共享资源或需要统一控制的场景(如配置管理、日志记录)。
使用场景
- 全局状态管理(如 Redux Store)。
- 共享组件(如模态框、提示框)。
- 工具类(如日志记录器、缓存管理)。
代码示例与详细讲解
示例 1:全局状态管理器
javascript
class Store {
static instance = null;
// 通过静态方法获取单例
static getInstance() {
if (!Store.instance) {
Store.instance = new Store();
}
return Store.instance;
}
constructor() {
if (Store.instance) {
throw new Error("Use Store.getInstance() instead of direct instantiation.");
}
this.state = {}; // 全局状态
}
// 更新状态
setState(key, value) {
this.state[key] = value;
}
// 获取状态
getState(key) {
return this.state[key];
}
}
// 使用示例
const store1 = Store.getInstance();
const store2 = Store.getInstance();
console.log(store1 === store2); // true(证明是同一个实例)
store1.setState("user", "Alice");
console.log(store2.getState("user")); // "Alice"
讲解:
- 通过
Store.getInstance()
获取单例,确保全局唯一。 - 直接调用
new Store()
会抛出错误,防止误用。 - 适用于需要统一管理全局状态的场景(如用户信息、主题配置)。
示例 2:模态框组件
ini
class Modal {
static instance = null;
static getInstance() {
if (!Modal.instance) {
Modal.instance = new Modal();
}
return Modal.instance;
}
constructor() {
if (Modal.instance) {
throw new Error("Modal instance already exists.");
}
// 创建模态框 DOM 元素
this.element = document.createElement("div");
this.element.innerHTML = `
<div class="modal" style="display: none;">
<p>This is a modal!</p>
<button>Close</button>
</div>
`;
document.body.appendChild(this.element);
}
show() {
this.element.style.display = "block";
}
hide() {
this.element.style.display = "none";
}
}
// 使用示例
const modal1 = Modal.getInstance();
const modal2 = Modal.getInstance();
console.log(modal1 === modal2); // true
modal1.show(); // 显示模态框
modal2.hide(); // 隐藏同一个模态框
讲解:
- 模态框的 DOM 元素只需创建一次,避免重复渲染。
- 通过单例确保全局只有一个模态框实例,防止页面中出现多个弹窗。
- 适用于提示框、对话框等需要全局唯一组件的场景。
示例 3:日志记录器
javascript
class Logger {
static instance = null;
static getInstance() {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
constructor() {
if (Logger.instance) {
throw new Error("Logger instance already exists.");
}
this.logs = [];
}
log(message) {
const timestamp = new Date().toISOString();
this.logs.push({ message, timestamp });
console.log(`[${timestamp}] LOG: ${message}`);
}
printLogHistory() {
console.log("Log History:");
this.logs.forEach(entry => console.log(`[${entry.timestamp}] ${entry.message}`));
}
}
// 使用示例
const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();
logger1.log("User logged in"); // [时间戳] LOG: User logged in
logger2.log("Data fetched"); // [时间戳] LOG: Data fetched
logger1.printLogHistory(); // 输出两条日志记录
讲解:
- 所有日志通过同一个实例记录,便于统一处理(如上传到服务器)。
- 避免每次记录日志时创建新实例的开销。
- 适用于需要集中管理日志、缓存、性能监控等工具类场景。
单例模式通过限制类的实例化次数,确保全局唯一性,适用于以下场景:
- 资源敏感型对象(如数据库连接池)。
- 需要共享状态的组件(如全局 Store)。
- 频繁访问的工具类(如日志记录器)。