单例模式
介绍
单例模式(Singleton Pattern)是一种常用的创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。单例模式在需要频繁创建和销毁对象、或对象创建成本较高的场景中非常有用。
原理
单例模式的核心原理包括:
- 私有构造函数:防止外部直接实例化类
- 静态实例变量:存储唯一实例
- 静态工厂方法:提供全局访问点
- 线程安全保证:确保在多线程环境下仍然只有一个实例
图示
+----------------+
| 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() {
// 单例方法
}
}
解决方案
应用场景
- 资源管理器:如数据库连接池、线程池
- 配置管理器:读取和管理配置文件
- 日志记录器:全局日志记录
- 缓存管理器:应用级缓存
最佳实践
- 根据需求选择实现方式:
- 单线程环境:饿汉式或懒汉式
- 多线程环境:双重检查锁定、静态内部类或枚举方式
- 防止反射攻击:在构造函数中检查实例是否已存在
- 防止序列化和反序列化破坏单例:实现readResolve()方法
- 考虑使用依赖注入:在大型应用中,依赖注入框架可以更好地管理单例
优缺点
优点:
- 确保只有一个实例,减少内存占用
- 避免重复创建对象,提高性能
- 提供全局访问点,方便使用
缺点:
- 违反单一职责原则
- 可能导致代码耦合度增加
- 不利于单元测试
工具推荐
- Lombok:提供@Singleton注解简化单例模式实现
- Spring Framework:通过IoC容器管理单例Bean
- Google Guice:依赖注入框架,支持单例作用域