第 1 天:单例模式(Singleton Pattern)—— 创建型模式

第 1 天:单例模式(Singleton Pattern)------ 创建型模式

1. 核心定义

单例模式确保一个类仅有一个实例 ,并提供一个全局访问点来获取该实例。它的核心是 "控制实例数量",避免重复创建消耗资源的对象(如数据库连接池、配置管理器)。

2. 解决的核心问题

  • 避免多个实例导致的资源浪费(如频繁创建数据库连接);
  • 防止多个实例引发的数据不一致(如配置文件读取实例,多实例可能导致配置冲突);
  • 提供统一的全局访问入口,简化对象调用。

3. 关键设计要点

  • 私有构造函数 :禁止外部通过 new 关键字创建实例;
  • 私有静态成员变量:存储类的唯一实例;
  • 公有静态方法:作为全局访问点,返回唯一实例(需处理线程安全问题)。

4. 常见实现方式(Java 示例)

方式 1:饿汉式(线程安全,简单但可能浪费资源)

"饿汉式" 在类加载时就创建实例,避免线程安全问题,但如果实例未被使用,会提前占用内存。

csharp 复制代码
public class HungrySingleton {
    // 1. 私有静态成员变量:类加载时创建唯一实例
    private static final HungrySingleton INSTANCE = new HungrySingleton();
    
    // 2. 私有构造函数:禁止外部new
    private HungrySingleton() {}
    
    // 3. 公有静态方法:返回实例
    public static HungrySingleton getInstance() {
        return INSTANCE;
    }
}

方式 2:懒汉式(线程不安全→线程安全优化)

"懒汉式" 在首次调用 getInstance() 时才创建实例,节省内存,但需额外处理线程安全(否则多线程下可能创建多个实例)。

线程安全优化版(双重检查锁定)

csharp 复制代码
public class LazySingleton {
    // 1. 私有静态成员变量:volatile防止指令重排序(关键!)
    private static volatile LazySingleton INSTANCE;
    
    // 2. 私有构造函数
    private LazySingleton() {}
    
    // 3. 公有静态方法:双重检查锁定
    public static LazySingleton getInstance() {
        // 第一次检查:避免已创建实例时的锁竞争
        if (INSTANCE == null) {
            synchronized (LazySingleton.class) {
                // 第二次检查:防止多线程同时进入第一个检查后重复创建
                if (INSTANCE == null) {
                    INSTANCE = new LazySingleton();
                }
            }
        }
        return INSTANCE;
    }
}

方式 3:静态内部类(推荐,线程安全且延迟加载)

利用 Java "静态内部类加载时机" 的特性:内部类在被调用时才加载,既实现延迟加载,又天然避免线程安全问题(类加载过程由 JVM 保证线程安全)。

csharp 复制代码
public class StaticInnerClassSingleton {
    // 1. 私有构造函数
    private StaticInnerClassSingleton() {}
    
    // 2. 静态内部类:存储唯一实例
    private static class SingletonHolder {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }
    
    // 3. 公有静态方法:调用内部类的实例
    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5. 应用场景

  • 系统中只能有一个实例的对象,如:

    • 数据库连接池(DataSource);
    • 配置文件管理器(读取全局配置);
    • 日志工具类(避免多实例写入日志时的冲突);
    • 操作系统的任务管理器、回收站。

6. 注意事项

  • 线程安全:懒汉式必须处理线程安全,否则多线程环境下会破坏 "单例" 特性;
  • 序列化问题 :若单例类实现 Serializable,需重写 readResolve() 方法,否则反序列化会创建新实例;
  • 反射攻击:私有构造函数可通过反射被调用,需在构造函数中添加判断(若实例已存在则抛异常)。
相关推荐
华仔啊17 分钟前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝1 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java
阿星AI工作室1 小时前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
Nyarlathotep01132 小时前
SpringBoot Starter的用法以及原理
java·spring boot
wuwen52 小时前
WebFlux + Lettuce Reactive 中 SkyWalking 链路上下文丢失的修复实践
java
SimonKing2 小时前
GitHub 10万星的OpenCode,正在悄悄改变我们的工作流
java·后端·程序员
Seven973 小时前
虚拟线程深度解析:轻量并发编程的未来趋势
java
雨中飘荡的记忆13 小时前
ElasticJob分布式调度从入门到实战
java·后端
_哆啦A梦21 小时前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding