跳到主要内容

单例模式

介绍

单例模式(Singleton Pattern)是一种常用的创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。单例模式在需要频繁创建和销毁对象、或对象创建成本较高的场景中非常有用。

原理

单例模式的核心原理包括:

  1. 私有构造函数:防止外部直接实例化类
  2. 静态实例变量:存储唯一实例
  3. 静态工厂方法:提供全局访问点
  4. 线程安全保证:确保在多线程环境下仍然只有一个实例

图示

+----------------+
| Singleton |
+----------------+
| - instance |
+----------------+
| - Singleton() |
| + getInstance()|
+----------------+

代码示例

饿汉式(线程安全)

public class Singleton {
// 静态实例,直接初始化
private static final Singleton instance = new Singleton();

// 私有构造函数
private Singleton() {
// 防止反射创建实例
if (instance != null) {
throw new RuntimeException("请使用getInstance()方法获取实例");
}
}

// 静态工厂方法
public static Singleton getInstance() {
return instance;
}
}

懒汉式(双重检查锁定)

public class Singleton {
// 使用volatile保证多线程环境下的可见性
private static volatile Singleton instance;

// 私有构造函数
private Singleton() {
// 防止反射创建实例
if (instance != null) {
throw new RuntimeException("请使用getInstance()方法获取实例");
}
}

// 静态工厂方法
public static Singleton getInstance() {
// 第一次检查
if (instance == null) {
// 同步锁
synchronized (Singleton.class) {
// 第二次检查
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

静态内部类方式

public class Singleton {
// 私有构造函数
private Singleton() {
// 防止反射创建实例
if (SingletonHolder.instance != null) {
throw new RuntimeException("请使用getInstance()方法获取实例");
}
}

// 静态内部类
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
}

// 静态工厂方法
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}

枚举方式

enum Singleton {
INSTANCE;

public void doSomething() {
// 单例方法
}
}

解决方案

应用场景

  1. 资源管理器:如数据库连接池、线程池
  2. 配置管理器:读取和管理配置文件
  3. 日志记录器:全局日志记录
  4. 缓存管理器:应用级缓存

最佳实践

  1. 根据需求选择实现方式
    • 单线程环境:饿汉式或懒汉式
    • 多线程环境:双重检查锁定、静态内部类或枚举方式
  2. 防止反射攻击:在构造函数中检查实例是否已存在
  3. 防止序列化和反序列化破坏单例:实现readResolve()方法
  4. 考虑使用依赖注入:在大型应用中,依赖注入框架可以更好地管理单例

优缺点

优点

  • 确保只有一个实例,减少内存占用
  • 避免重复创建对象,提高性能
  • 提供全局访问点,方便使用

缺点

  • 违反单一职责原则
  • 可能导致代码耦合度增加
  • 不利于单元测试

工具推荐

  1. Lombok:提供@Singleton注解简化单例模式实现
  2. Spring Framework:通过IoC容器管理单例Bean
  3. Google Guice:依赖注入框架,支持单例作用域