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

ops/2025/2/27 18:12:18/

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

文章目录

一、入门

什么是单例模式

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

为什么要单例模式

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

如何实现单例模式

  1. 私有构造函数:防止外部通过 new 创建实例。
  2. 静态私有实例:类内部持有唯一的实例。
  3. 静态公有方法:提供全局访问点,返回唯一实例。
    饿汉式
java">public class Singleton {// 在类加载时就创建实例private static final Singleton INSTANCE = new Singleton();// 私有构造函数,防止外部通过 new 创建实例private Singleton() {}// 提供全局访问点public static Singleton getInstance() {return INSTANCE;}
}
  • 实例在类加载时立即创建。
  • 无论是否使用,实例都会提前初始化。

特点

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

懒汉式

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

双重检查(DCL)

java">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;}
}
  • 优点:线程安全且性能较好。
  • 缺点:实现稍复杂。

静态内部类

java">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),只有在需要时才创建实例。

枚举

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

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

Java 标准库 RunTime类

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

java">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 容器中只有一个实例。
java">@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.ppmy.cn/ops/161744.html

相关文章

暨南大学智科院电子信息复试Tips

暨南大学智科院人工智能(电子信息)的总成绩初试成绩X初试权重复试折合成绩X复试权重(复试权重为50%,初试权重为50%),也就是说复试占比与初试占比五五开,所以复试也是非常重要的,往年都有初试高分选手复试被刷的情况,同…

【Python爬虫(90)】以Python爬虫为眼,洞察金融科技监管风云

【Python爬虫】专栏简介:本专栏是 Python 爬虫领域的集大成之作,共 100 章节。从 Python 基础语法、爬虫入门知识讲起,深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑,覆盖网页、图片、音频等各类数据爬取&#xff…

爬虫解析库:parsel的详细使用

文章目录 1. 安装 Parsel2. 基本用法3. 使用 CSS 选择器提取数据4. 使用 XPath 提取数据5. 链式调用6. 正则表达式提取7. 处理嵌套元素8. 处理默认值9. 结合 Requests 使用10. 处理复杂 HTML11. 性能优化12. 注意事项 引言:本博客详细介绍爬虫解析库parser的详细使用…

读书笔记 - 码农心得(重学Java设计模式)

读书笔记 - 码农心得(重学Java设计模式) 粗暴的开发方式可以归纳为三步:定义属性,创建方法,调用展示。虽然初次实现很快,但不便于后期维护和扩展。 真正好的代码不只为了完成现有功能,更会考虑后…

C++ | 设计模式 | 代理模式

代理模式(Proxy Pattern) 代理模式是一种结构型设计模式 ,它为某个对象提供一个代理,以控制对该对象的访问。代理模式可以在不改变原始对象的情况下,通过引入代理对象来扩展功能或控制对原始对象的访问。 核心思想 代…

WPS接入DeepSeek模型免费版本

WPS灵犀正式上线DeepSeek R1! 参考原文:WPS接入DeepSeek模型免费版本 今年年初,WPS 官方正式发布重磅消息:WPS 全面接入 DeepSeek R1 大模型。用户只需将 WPS 更新到最新版本,登录账号后,点击界面左侧的「…

解锁C# XML编程:从新手到实战高手的蜕变之路

一、引言:XML 在 C# 中的关键地位 在 C# 开发的广袤领域中,XML(可扩展标记语言,eXtensible Markup Language)宛如一颗璀璨的明星,占据着举足轻重的地位。它以其独特的结构化和自描述特性,成为了…

IDEA创建Spring配置文件Spring Config的方法

作为刚刚开始学Spring框架的小白,而且我也是刚刚学怎么用idea,不会简单的操作也是很正常的是吧。这个问题其实只是我傻傻的不懂,是个很简单的问题,我现在把它记录下来。 在idea创建maven项目后,我们在左边右键新建xml文…