当前位置: 首页 > news >正文

【JS】什么是单例模式

哎,写这玩意就得白话一段,初学js时,只知道写出来的代码能实现出来自己想要的东西,自己就不会过多的去关注其他,但随着做开发时间长了,自己也想去开发点东西,或者去理解一些其他人的代码时,总会有着不清楚,看不懂的尴尬。

初听单例模式时,还是在一次面试,面试官问什么是单例模式,大脑直接宕机了,单例模式,听说过工厂模式,没听说过单例模式啊,尴尬啊,现在其实也不清楚。

趁着这个机会,就一起学习一下,整理一下单例模式,让它彻底转化为我之利刃,为我们所用。

文章目录

      • 什么是单例模式?
      • 为什么要用?
      • 特点
      • 关键实现要点
      • 实现方式
        • 1.对象字面量
        • 2.闭包实现
        • 3.Class实现
        • 模块模式
      • 适用场景
      • 实际应用场景例子
        • 全局状态管理
        • 缓存管理器
        • 日志管理器
        • 全局事件总线
      • 总结

什么是单例模式?

单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个唯一的实例。

您可以把它想象成:

  • 国家的总统:一个国家在任期内只有一位总统。
  • 电脑的回收站:无论你从哪个磁盘分区删除文件,打开的都是同一个回收站。
  • 任务管理器:一个系统中的任务管理器实例只能有一个,这样才能方便系统去统筹所有的任务。

为什么要用?

在一些场景的前提下,我们需要某个对象,在全局的范围中,有且仅有一个对象实例的存在,这样方便我们全局的访问以及管理。

如果创建了多个实例,会导致一些我们所不期望的问题:

  • 资源浪费
  • 数据不一致
  • 程序执行不统一

特点

优点:

  • 保证一个类只有一个实例
  • 提供全局访问点
  • 避免重复创建对象,节省内存

缺点:

  • 违反单一职责原则
  • 可能产生隐藏的依赖关系
  • 不利于单元测试(难以模拟)

关键实现要点

要实现一个单例,通常需要做到以下两点:

  1. 私有化构造函数:防止外部使用 new 关键字随意创建多个实例。
  2. 提供一个静态方法(如 getInstance),该方法负责检查实例是否已经存在:
    • 如果已存在,则返回这个已有的实例。
    • 如果不存在,则创建一个新的实例并返回,同时将其保存下来以备下次使用。

实现方式

1.对象字面量
const Singleton = {instanceId:Math.random(),//使用instanceid作为单例的唯一标志config: {apiUrl: 'https://api.example.com',timeout: 5000},getData() {console.log('Getting data from:', this.config.apiUrl);},updateConfig(newConfig) {this.config = { ...this.config, ...newConfig };}
}// 使用
Singleton.getData();
Singleton.updateConfig({ timeout: 3000 });
2.闭包实现
const Singleton = (function() {let instance;function createInstance() {const object = {counter: 0,increment() {this.counter++;console.log('Counter:', this.counter);},getCounter() {return this.counter;}};return object;}return {getInstance() {if (!instance) {instance = createInstance();}return instance;}};
})();// 使用
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();instance1.increment(); // Counter: 1
instance2.increment(); // Counter: 2
console.log(instance1 === instance2); // true
3.Class实现
class Singleton {static instance;constructor() {if (Singleton.instance) {return Singleton.instance;}this.data = [];this.createdAt = new Date();Singleton.instance = this;}addItem(item) {this.data.push(item);}getItems() {return this.data;}static getInstance() {if (!Singleton.instance) {Singleton.instance = new Singleton();}return Singleton.instance;}
}// 使用
const instance1 = new Singleton();
const instance2 = new Singleton();
const instance3 = Singleton.getInstance();console.log(instance1 === instance2); // true
console.log(instance1 === instance3); // trueinstance1.addItem('item1');
console.log(instance2.getItems()); // ['item1']
模块模式
// configManager.js
let instance = null;
let config = {};class ConfigManager {constructor() {if (instance) {return instance;}this.defaultConfig = {theme: 'dark',language: 'zh-CN',apiBaseUrl: 'https://api.example.com'};instance = this;}setConfig(newConfig) {config = { ...this.defaultConfig, ...newConfig };}getConfig(key) {return key ? config[key] : config;}reset() {config = { ...this.defaultConfig };}
}export default new ConfigManager();// 使用
import configManager from './configManager.js';configManager.setConfig({ theme: 'light' });
console.log(configManager.getConfig('theme')); // 'light'

适用场景

  • 全局配置对象
  • 缓存系统
  • 日志记录器
  • 数据库连接池
  • 状态管理器

实际应用场景例子

全局状态管理
class GlobalState {static instance;constructor() {if (GlobalState.instance) {return GlobalState.instance;}this.state = {};this.listeners = new Map();GlobalState.instance = this;}setState(key, value) {this.state[key] = value;this.notify(key, value);}getState(key) {return this.state[key];}subscribe(key, callback) {if (!this.listeners.has(key)) {this.listeners.set(key, new Set());}this.listeners.get(key).add(callback);// 返回取消订阅函数return () => {this.listeners.get(key)?.delete(callback);};}notify(key, value) {this.listeners.get(key)?.forEach(callback => {callback(value);});}
}// 使用
const stateManager = new GlobalState();// 订阅状态变化
const unsubscribe = stateManager.subscribe('user', (user) => {console.log('User updated:', user);
});stateManager.setState('user', { name: 'John', age: 30 });
缓存管理器
class CacheManager {static instance;constructor() {if (CacheManager.instance) {return CacheManager.instance;}this.cache = new Map();this.ttl = new Map(); // 生存时间CacheManager.instance = this;}set(key, value, ttlMs = 60000) {this.cache.set(key, value);this.ttl.set(key, Date.now() + ttlMs);// 自动清理过期缓存setTimeout(() => {if (this.ttl.get(key) <= Date.now()) {this.delete(key);}}, ttlMs);}get(key) {const expiry = this.ttl.get(key);if (expiry && expiry <= Date.now()) {this.delete(key);return null;}return this.cache.get(key);}delete(key) {this.cache.delete(key);this.ttl.delete(key);}clear() {this.cache.clear();this.ttl.clear();}
}// 使用
const cache = new CacheManager();
cache.set('user-data', { id: 1, name: 'Alice' }, 5000);setTimeout(() => {console.log(cache.get('user-data')); // null (已过期)
}, 6000);
日志管理器
const Logger = (function() {let instance;let logs = [];class LoggerClass {constructor() {if (instance) {return instance;}instance = this;}log(level, message) {const logEntry = {timestamp: new Date().toISOString(),level,message};logs.push(logEntry);console[level](`[${logEntry.timestamp}] ${message}`);}info(message) {this.log('info', message);}error(message) {this.log('error', message);}warn(message) {this.log('warn', message);}getLogs() {return [...logs];}clear() {logs = [];}}return new LoggerClass();
})();// 使用
Logger.info('Application started');
Logger.error('Something went wrong');
console.log(Logger.getLogs());
全局事件总线
class EventBus {static instance;constructor() {if (EventBus.instance) {return EventBus.instance;}this.events = {};EventBus.instance = this;}on(event, callback) {if (!this.events[event]) {this.events[event] = [];}this.events[event].push(callback);}emit(event, data) {if (this.events[event]) {this.events[event].forEach(callback => callback(data));}}
}// 不同模块间通信
const eventBus = new EventBus();// 用户模块
eventBus.on('userLogin', (user) => {console.log('用户登录:', user.name);
});// 购物车模块
eventBus.on('userLogin', (user) => {console.log('加载用户购物车');
});

总结

特点描述
目的控制实例数目,节省资源,保证全局一致性。
核心一个类只有一个实例。
实现私有构造器 + 静态获取方法。
用途全局配置、日志记录、数据库连接池、对话框、缓存系统等。

希望这个解释能帮助您彻底理解单例模式!它是一个在软件开发中非常基础且实用的模式,同时,JavaScript 的单例模式相比其他语言更灵活。

http://www.dtcms.com/a/435184.html

相关文章:

  • 昆明网站建设优化企业wap网站 微信小程序
  • wordpress 网站统计插件网站建设网页开发
  • 网站内容维护费用灯光设计网站推荐
  • pink老师html5+css3day02
  • CTFHub 信息泄露通关笔记4:备份文件下载 bak文件
  • OverlayManager service, overlay, idmap, rro, android
  • 如何拆解一个Java项目?
  • C++ 泛型和特化
  • 【Linux篇】Linux指令进阶:从入门到熟练的实操指南
  • Orleans流系统时序图
  • 专业网站建设价格分析企业建设网站好吗
  • 活动日志系统集成指南
  • 弹幕网站是怎么做的软件开发工程师级别
  • 贵阳市建设局信息管理网站中国建设会计学网站
  • 函数简单传入参数的汇编分析
  • 怎样做已有网站的编辑维护大沥九江网站制作
  • 自己网站首页如何设置网站托管维护方案
  • 安卓基础组件024-底部导航栏
  • 【ROS2学习笔记】话题通信篇:话题通信项目实践——系统状态监测与可视化工具
  • 苏州门户网站平台推广员
  • ICT 数字测试原理 4 --电源监控电路(PMC)
  • 网站内页要不要加上关键词和描述广告型网站怎么做的
  • 深圳市建设局工程交易中心网站贵州 网站建设
  • 【C/C++】 函数形参—指针传递
  • 门限签名与多方安全计算(MPC)
  • 东莞公司高端网站建设高大上网站
  • 基于websocket的多用户网页五子棋(一)
  • PCA 主成分分析:数据世界的 “旅行清单整理师”—— 从 30 维杂乱到 2 维清晰的诗意降维
  • wordpress兼容mipseo加盟代理
  • 台州网站排名优化费用网站建设设计风格描述