当前位置: 首页 > article >正文

【设计模式】【创建型模式】单例模式(Singleton)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中… 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
🎵 当你的天空突然下了大雨,那是我在为你炸乌云

文章目录

  • 一、入门
    • 什么是单例模式?
    • 为什么要单例模式?
    • 如何实现单例模式?
      • 懒汉式
      • 双重检查(DCL)
      • 静态内部类
      • 枚举
  • 二、单例模式在框架源码中的运用
    • Java 标准库 RunTime类
    • Spring Framework
  • 三、总结
    • 单例模式的优点
    • 单例模式的缺点
    • 单例模式的适用场景

一、入门

什么是单例模式?

单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。

为什么要单例模式?

  1. 节省资源
    • 场景:某些对象创建和销毁成本高,如数据库连接池、线程池等。
    • 原因:单例模式确保这些资源只创建一次,避免重复创建和销毁,节省系统资源。
  2. 全局访问点
    • 场景:需要在多个模块或组件中共享同一个对象,如配置管理器、日志记录器等。
    • 原因:单例模式提供一个全局访问点,方便不同模块共享同一实例,避免频繁传递对象。
  3. 保持一致性
    • 场景:需要确保某些操作或状态在整个应用中保持一致,如缓存管理、计数器等。
    • 原因:单例模式确保只有一个实例,避免多个实例导致状态不一致。
  4. 控制实例数量
    • 场景:某些情况下,限制实例数量是必要的,如打印机管理、文件系统等。
    • 原因:单例模式确保只有一个实例存在,避免资源冲突或竞争条件。
  5. 简化设计
    • 场景:某些设计模式(如工厂模式、抽象工厂模式)中,单例模式可以简化对象创建和管理。
    • 原因:单例模式减少对象创建的复杂性,使设计更简洁。

如何实现单例模式?

  1. 私有构造函数:防止外部通过 new 创建实例。
  2. 静态私有实例:类内部持有唯一的实例。
  3. 静态公有方法:提供全局访问点,返回唯一实例。
    饿汉式
public class Singleton {
    // 在类加载时就创建实例
    private static final Singleton INSTANCE = new Singleton();

    // 私有构造函数,防止外部通过 new 创建实例
    private Singleton() {}

    // 提供全局访问点
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
  • 实例在类加载时立即创建。
  • 无论是否使用,实例都会提前初始化。

特点

  1. 线程安全:实例在类加载时创建,由 JVM 保证线程安全。
  2. 提前加载:无论是否使用,实例都会在类加载时创建,可能会占用资源。
  3. 实现简单:代码简洁,无需考虑多线程问题。

懒汉式

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
  • 优点:线程安全。
  • 缺点:每次调用都加锁,性能较差。

双重检查(DCL)

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 优点:线程安全且性能较好。
  • 缺点:实现稍复杂。

静态内部类

public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • 优点:线程安全,延迟加载,实现简单。
  • 因为实例的创建由 JVM 在类加载时完成,且静态内部类的加载是线程安全的。
  • 实例在第一次调用 getInstance() 时创建。
  • 延迟加载(Lazy Initialization),只有在需要时才创建实例。

枚举

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        // 业务逻辑
    }
}
  • 优点:线程安全,防止反射攻击,简洁。

二、单例模式在框架源码中的运用

Java 标准库 RunTime类

Runtime 类Runtime 类是典型的单例模式实现,用于管理应用程序的运行环境。

public class Runtime {
    private static final Runtime currentRuntime = new Runtime();
    private Runtime() {}
    public static Runtime getRuntime() {
        return currentRuntime;
    }
}
  • 通过 Runtime.getRuntime() 获取唯一的 Runtime 实例。

Spring Framework

Spring 框架中的单例模式主要用于管理 Bean 的生命周期。
Spring 的默认 Bean 作用域

  • Spring 容器中的 Bean 默认是单例的(Singleton 作用域),即每个 Spring 容器中只有一个实例。
@Service
public class UserService {
    // UserService 在 Spring 容器中是单例的
}

@Service
@Scope("singleton") // 默认就是单例,可以省略
public class UserService {
}

单例 Bean 的管理

  • Spring 容器通过单例模式确保全局唯一的 Bean 实例,避免重复创建。
  • 示例:Spring 的 ApplicationContext 本身就是单例的。

三、总结

单例模式的优点

  1. 全局唯一访问点
    • 单例模式确保一个类只有一个实例,并提供一个全局访问点,方便其他模块或组件共享该实例。
    • 示例:配置管理器、日志记录器等。
  2. 节省资源
    • 对于创建成本高的对象(如数据库连接池、线程池),单例模式可以避免重复创建和销毁,节省系统资源。
    • 示例:数据库连接池通常只需要一个实例来管理所有连接。
  3. 保持一致性
    • 单例模式确保全局状态的一致性,避免多个实例导致状态冲突。
    • 示例:缓存管理器需要确保缓存数据的一致性。
  4. 简化设计
    • 单例模式可以减少对象创建的复杂性,使代码更简洁。
    • 示例:Spring 框架中的单例 Bean 管理。
  5. 线程安全(某些实现)
    • 通过正确的实现(如饿汉式、静态内部类、枚举),单例模式可以保证线程安全。

单例模式的缺点

  1. 难以扩展
    • 单例模式通常通过私有构造函数限制实例化,导致难以扩展或修改。
    • 如果需要多个实例或修改单例行为,可能需要重构代码。
  2. 隐藏依赖
    • 单例模式通过全局访问点获取实例,可能导致代码的依赖关系不清晰,增加调试和维护难度。
  3. 测试困难
    • 单例模式的全局状态可能导致单元测试困难,因为测试用例之间可能会相互影响。
    • 示例:测试一个依赖单例类的模块时,可能需要重置单例状态。
  4. 可能滥用
    • 单例模式容易被滥用,导致系统中出现大量全局状态,增加代码的耦合性。
  5. 生命周期管理问题
    • 单例模式的生命周期通常与应用程序一致,可能导致资源无法及时释放。
    • 示例:单例对象持有数据库连接,可能导致连接无法关闭。

单例模式的适用场景

  1. 全局唯一对象
    • 需要全局唯一的对象时,可以使用单例模式。
    • 示例:
      • 配置管理器(ConfigManager)。
      • 日志记录器(Logger)。
      • 数据库连接池(DataSource)。
  2. 资源密集型对象
    • 对于创建成本高的对象,单例模式可以避免重复创建和销毁。
    • 示例:
      • 线程池(ThreadPool)。
      • 缓存管理器(CacheManager)。
  3. 共享状态管理
    • 需要全局共享状态时,可以使用单例模式。
    • 示例:
      • 计数器(Counter)。
      • 全局锁(Lock)。
  4. 工具类
    • 对于无状态的工具类,单例模式可以避免重复创建实例。
    • 示例:
      • 日期格式化工具(DateUtils)。
      • 字符串处理工具(StringUtils)。
  5. 框架核心组件
    • 在框架中,单例模式常用于管理核心组件。
    • 示例:
      • Spring 的 ApplicationContext
      • MyBatis 的 SqlSessionFactory

http://www.kler.cn/a/557002.html

相关文章:

  • golang时间相关函数总结
  • ZLG嵌入式笔记 | 为什么你的网卡工作会不正常?(上
  • Typora的Github主题美化
  • Service Mesh在爱奇艺的落地实践:架构、运维与扩展
  • 微服务即时通信系统---(二)框架学习
  • 迪威模型:引领 3D 模型轻量化技术革新
  • vue从入门到精通(十一):条件渲染
  • 股票与比特币投资困境分析及解决方案
  • FFmpeg中的编码和解码流程
  • 实现动态翻转时钟效果的 HTML、CSS 和 JavaScript,附源码
  • RPC:分布式系统的通信桥梁
  • 【MySQL】索引和视图
  • 【CXX】5 桥接模块参考
  • 【够用就好005】-在VSCode中管理ECS服务器的实操步骤
  • MYSQL的第一次
  • AI赋能编程:PyCharm与DeepSeek的智能开发革命
  • 一周学会Flask3 Python Web开发-客户端状态信息Cookie以及加密
  • 2025.2.23机器学习笔记:PINN文献阅读
  • Day 45 卡玛笔记
  • qt5实现表盘的旋转效果,通过提升QLabel类