设计模式-单例模式

日常开发,单例设计模式是解决常用的设计模式之一。今天我们来深入探讨单例模式(Singleton Pattern),这个看似简单却应用广泛的设计模式。

什么是单例模式

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

核心特征:

  • 全局唯一性:整个应用程序中只存在一个实例
  • 延迟实例化:通常在第一次使用时才创建实例
  • 全局访问:提供静态方法获取实例

单例模式的几种实现方式

1. 饿汉式(Eager Initialization)

js 复制代码
class EagerSingleton {
  private static instance = new EagerSingleton();
  
  private constructor() {}
  
  static getInstance(): EagerSingleton {
    return EagerSingleton.instance;
  }
}

特点: 类加载时就创建实例,线程安全但可能浪费内存。

2. 懒汉式(Lazy Initialization)

js 复制代码
class LazySingleton {
  private static instance: LazySingleton;
  
  private constructor() {}
  
  static getInstance(): LazySingleton {
    if (!LazySingleton.instance) {
      LazySingleton.instance = new LazySingleton();
    }
    return LazySingleton.instance;
  }
}

特点: 第一次使用时才创建,节省内存但需考虑线程安全。

3. 双重检查锁定(Double-Checked Locking)

js 复制代码
class DoubleCheckSingleton {
  private static instance: DoubleCheckSingleton;
  private static creating = false;
  
  private constructor() {}
  
  static getInstance(): DoubleCheckSingleton {
    if (!DoubleCheckSingleton.instance) {
      if (!DoubleCheckSingleton.creating) {
        DoubleCheckSingleton.creating = true;
        DoubleCheckSingleton.instance = new DoubleCheckSingleton();
        DoubleCheckSingleton.creating = false;
      }
    }
    return DoubleCheckSingleton.instance;
  }
}

前端业务中的真实使用场景

1. 用户信息管理

js 复制代码
// 实名信息单例对象
export class UserInfo {
  private static instance: UserInfo;

  id: string = '';
  account: string = '';
  realname: string | null = null;
  // ... 其他属性

  private constructor() {
    // 私有构造函数防止外部实例化
  }

  static getInstance(): UserInfo {
    if (!UserInfo.instance) {
      UserInfo.instance = new UserInfo();
    }
    return UserInfo.instance;
  }

  updateFromResponse(data: any): void {
    this.id = data.id || this.id;
    this.account = data.account || this.account;
    // ... 
  }

  clear(): void {
    this.id = '';
    this.account = '';
    // ... 
  }
}

// 使用
const userInfo = UserInfo.getInstance();
userInfo.updateFromResponse(apiResponse);

2. 全局配置管理

js 复制代码
class AppConfig {
  private static instance: AppConfig;
  
  private config = {
    apiBaseUrl: '',
    theme: 'light',
    language: 'zh-CN'
  };

  static getInstance() {
    if (!AppConfig.instance) {
      AppConfig.instance = new AppConfig();
    }
    return AppConfig.instance;
  }

  setConfig(key: string, value: any) {
    this.config[key] = value;
  }

  getConfig(key: string) {
    return this.config[key];
  }
}

3. 事件总线

js 复制代码
class EventBus {
  private static instance: EventBus;
  private events: Map<string, Function[]> = new Map();

  static getInstance() {
    if (!EventBus.instance) {
      EventBus.instance = new EventBus();
    }
    return EventBus.instance;
  }

  on(event: string, callback: Function) {
    if (!this.events.has(event)) {
      this.events.set(event, []);
    }
    this.events.get(event)!.push(callback);
  }

  emit(event: string, data?: any) {
    const callbacks = this.events.get(event);
    if (callbacks) {
      callbacks.forEach(callback => callback(data));
    }
  }
}

4. 缓存管理器

js 复制代码
class CacheManager {
  private static instance: CacheManager;
  private cache = new Map<string, { data: any, expiry: number }>();

  static getInstance() {
    if (!CacheManager.instance) {
      CacheManager.instance = new CacheManager();
    }
    return CacheManager.instance;
  }

  set(key: string, data: any, ttl = 5 * 60 * 1000) {
    this.cache.set(key, {
      data,
      expiry: Date.now() + ttl
    });
  }

  get(key: string) {
    const item = this.cache.get(key);
    if (!item) return null;
    
    if (Date.now() > item.expiry) {
      this.cache.delete(key);
      return null;
    }
    
    return item.data;
  }
}

SSM框架中的单例模式

最近又想复习一下SSM,所以也顺带讲一下SSM中的单例模式

1. Spring 中的单例

Spring 容器中的 Bean 默认是单例的(只是默认):

js 复制代码
@Service
public class UserService {
    // Spring 容器保证全局唯一
}

@Component
@Scope("singleton") // 显式声明单例
public class ConfigService {
    
}

2. MyBatis 中的单例

js 复制代码
// SqlSessionFactory 通常作为单例使用
public class MyBatisConfig {
    private static SqlSessionFactory sqlSessionFactory;
    
    public static SqlSessionFactory getSqlSessionFactory() {
        if (sqlSessionFactory == null) {
            // 初始化逻辑
        }
        return sqlSessionFactory;
    }
}

3. 数据库连接池

js 复制代码
public class DatabasePool {
    private static volatile DatabasePool instance;
    private DataSource dataSource;
    
    private DatabasePool() {
        // 初始化连接池
    }
    
    public static DatabasePool getInstance() {
        if (instance == null) {
            synchronized (DatabasePool.class) {
                if (instance == null) {
                    instance = new DatabasePool();
                }
            }
        }
        return instance;
    }
}

单例模式的优缺点

优点

  • 内存节省:避免重复创建对象
  • 全局访问:提供统一的访问入口
  • 状态共享:便于在不同模块间共享状态(这个其实在react中也是非常好用的)
  • 延迟加载:按需创建,提高启动性能

单例模式在开发中还是非常常见的,至少一个项目中是有好几处的,然后了解设计模式也能提高编程思维,合适的时候用合适的算法,不要过度使用,明明不适合非常那些写,那么写出来也是十扇,永远以确保代码的可维护性和可测试性为标准编写代码。

相关推荐
刘卓航众创芯云服务部35 分钟前
Kimi K3复杂任务实测:我把团队最头疼的三个场景全跑了一遍
前端
cll_8692418911 小时前
一个好看的Wordpress博客文字css样式
前端·css·ui
武子康1 小时前
Shippy:确定性工具、会话级 Sandbox 与 Live-Data Eval(4 类收敛 + 7 步实现方案 + 6 类评测指标)
前端·人工智能·后端
糖果店的幽灵1 小时前
langgraph分支之 - 动态分支(Dynamic Branch)
java·前端·javascript·人工智能·langgraph
meilindehuzi_a1 小时前
Workflow 与 Agent 有什么区别:从 LangChain 流水线到智能体决策
前端·人工智能
三翼鸟数字化技术团队1 小时前
一种前端大屏适配方案
前端·css
小四的小六2 小时前
WebView 在 AI 时代的三个被低估的价值——从自己的 AI 产品里找到的答案
前端·openai·ai编程
电子科技圈2 小时前
先进封装、芯粒架构和3D集成——先进异构集成亟需兼具标准化与定制化能力的互联及总线IP解决方案
tcp/ip·设计模式·架构·软件构建·代码规范·设计规范
程序员黑豆2 小时前
鸿蒙应用开发:ForEach 循环渲染用法详解
前端·harmonyos
JarvanMo2 小时前
HTTP 迎来 16 年来首个全新请求方法:`QUERY`
前端