模式概述
单例模式(Singleton Pattern)是设计模式中最基础但应用最广泛的创建型模式之一,确保一个类仅有一个实例,并提供一个全局访问点。这种模式在需要全局唯一对象的场景中至关重要,如配置管理、线程池、数据库连接池等。
简单代码示例(五种经典实现方式对比)
- 饿汉式(线程安全)
特点:线程安全但可能造成资源浪费
public class EagerSingleton {
// 类加载时立即初始化(占用内存)
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {} // 私有构造
public static EagerSingleton getInstance() {
return instance;
}
}
- 懒汉式(线程不安全)
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton(); // 多线程下可能创建多个实例
}
return instance;
}
}
- 同步方法懒汉式(线程安全)
public class SynchronizedSingleton {
private static SynchronizedSingleton instance;
private SynchronizedSingleton() {}
// 方法同步降低性能
public static synchronized SynchronizedSingleton getInstance() {
if (instance == null) {
instance = new SynchronizedSingleton();
}
return instance;
}
}
- 双重检查锁定(DCL)
关键点:volatile防止指令重排序,避免返回未初始化完成的对象
public class DoubleCheckedSingleton {
// volatile保证可见性和有序性
private volatile static DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) { // 第二次检查
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
- 静态内部类
public class StaticNestedSingleton {
private StaticNestedSingleton() {}
// 静态内部类在首次使用时加载
private static class SingletonHolder {
private static final StaticNestedSingleton INSTANCE = new StaticNestedSingleton();
}
public static StaticNestedSingleton getInstance() {
return SingletonHolder.INSTANCE; // 由JVM保证线程安全
}
}
- 枚举实现(防序列化破坏)
《Effective Java》推荐方案:无偿提供序列化机制,防止反射攻击
public enum EnumSingleton {
INSTANCE; // 枚举常量本身就是单例
public void doSomething() {
System.out.println("Singleton working");
}
}
// 使用方式:EnumSingleton.INSTANCE.doSomething();
技术细节
1.模式组成
组件 | 职责说明 |
---|---|
Singleton | 单例 |
2.优缺点
优点
- 资源高效利用,减少内存开销:避免重复创建相同对象
- 全局访问点,统一入口管理共享资源
- 性能优化,减少对象创建开销(尤其重量级对象)
缺点
- 违反单一职责原则
- 测试困难,难以模拟依赖
- 扩展性差,难以通过继承扩展功能
模式应用
Springboot中默认实例化的对象是单例,如果想声明成多例对象可以使用@Scope(“prototype”)