设计模式——Singleton(单例)设计模式
摘要
本文介绍了单例设计模式的概念、实现和应用场景。单例模式确保某个类只有一个实例,节省资源并提供全局访问点。文章详细解释了单例模式的实现要素,包括私有构造方法、静态实例和公共静态方法,并探讨了其在数据库连接池、日志记录器和配置管理器等场景中的应用。
1. 单例设计模式是什么
1.1. 单例模式理解
单例设计模式(Singleton Pattern)是一种常见的创建型设计模式,旨在确保某个类在整个应用程序中只有一个实例,并提供一个全局访问点。这个模式的主要目的就是控制类的实例化过程,避免在程序运行期间多个实例的创建。它在需要全局唯一实例时非常有用,例如配置管理器、日志记录器等。
1.2. 单例模式核心概念
单例模式的核心概念就是 唯一性 和 全局访问,通过私有化构造方法、提供全局访问点、延迟实例化、确保线程安全等手段来实现其目标。通过使用单例模式,可以有效地控制类的实例化和资源管理,避免冗余实例的创建。
单例设计模式的核心概念是确保某个类在整个应用程序中只有一个实例,并且提供一个全局访问点来访问该实例。其核心思想可以总结为以下几点:
- 唯一性:单例模式的主要目的是保证某个类只有一个实例。在程序的整个生命周期中,无论调用多少次获取实例的方法,都只能返回同一个实例。这避免了系统中多个相同对象的存在,确保了资源的统一管理和共享。
- 全局访问:单例模式提供一个全局访问点,使得该唯一实例可以在系统的任何地方被访问。通常这个访问点是通过一个静态方法实现的,外部通过该方法访问实例,而不需要直接创建实例。
- 延迟初始化:虽然单例模式保证了唯一性,但通常在实际使用时,实例的创建是延迟的(即懒加载)。实例只有在第一次被访问时才会被创建。这样可以避免在程序启动时就创建实例,节省资源,提升性能。
- 私有构造方法:为了确保类只能创建一个实例,单例模式通常会将构造方法设为私有的,阻止外部直接调用构造方法创建实例。这样,外部只能通过提供的静态方法来获取实例。
- 线程安全:在多线程环境下,需要保证实例的创建是线程安全的,防止多个线程同时创建多个实例。因此,单例模式在实现时需要考虑线程同步,以避免并发问题。
- 避免反射和序列化破坏单例:为了防止反射攻击或者序列化和反序列化破坏单例模式,一些实现方式(如枚举方式)能够防止通过反射创建新的实例。通过这种方式,确保了单例模式的安全性。
1.3. 单例设计模式作用
单例设计模式的作用可以总结为以下三点:
- 确保唯一性:单例模式保证某个类只有一个实例,避免了多个实例造成的资源浪费和管理混乱。例如,数据库连接池通常使用单例模式来确保在整个应用中只创建一个连接池实例,避免了多次创建和销毁连接池的开销。
- 提供全局访问点:单例模式通过静态方法提供一个全局访问点,使得系统的各个部分可以共享和访问该唯一实例。例如,日志记录器类通常使用单例模式,确保全局只有一个日志实例,且所有模块都通过该实例记录日志。
- 节省资源:单例模式通常采用懒加载(延迟实例化)策略,只有在第一次需要时才创建实例,从而节省系统资源。例如,配置管理器类可以使用单例模式来确保只加载一次配置文件,而不是每次读取时都创建新的实例。
2. 单例设计模式类实现

我们通过一个单例类 来确保该类只有一个实例,并且提供一个全局访问点来获取该实例。单例模式的实现通常需要包含以下几个核心要素:
- 私有构造方法:禁止外部通过构造方法直接创建实例。
- 静态实例:持有类的唯一实例。
- 公共静态方法:提供一个公共的访问点来获取唯一实例。
3. 单例模式使用场景
在实际工作中,单例模式有着广泛的应用,尤其是在需要确保全局唯一实例、共享资源或进行全局配置管理的场景。以下是几个常见的单例模式具体使用场景,并说明每个场景的作用:
3.1. 数据库连接池
场景:在开发大型系统时,数据库连接池通常会使用单例模式。一个数据库连接池是一个可以复用数据库连接的对象,在系统中通常只需要一个池来管理所有的数据库连接。通过单例模式,可以确保连接池在应用程序中只有一个实例,避免每次数据库操作都创建新的连接池实例,降低系统开销。
作用:
- 确保唯一性:通过单例模式,数据库连接池在整个应用中只有一个实例,避免了多次创建池的开销。
- 资源共享:确保多个数据库操作共享同一个连接池实例,提高连接的复用率,节省系统资源。
- 性能优化:通过连接池管理,可以减少数据库连接的创建和销毁的成本,提升系统的性能。
3.2. 日志记录器
场景:系统中的日志记录器通常使用单例模式来确保全局只有一个日志实例。日志系统需要将日志记录到文件或数据库等地方,如果每个模块都实例化一个新的日志对象,不仅浪费内存,还可能导致日志信息混乱。
作用:
- 确保唯一性:确保整个系统中只有一个日志记录器实例,避免了多个日志对象的创建。
- 全局共享:所有模块通过该单一日志实例记录日志,确保日志格式和记录方式的一致性。
- 降低内存消耗:避免了不必要的日志对象创建和销毁,提高了系统资源的利用率。
3.3. 配置管理器(RocketMQTemplate等类)
场景:配置文件(如数据库连接配置、系统参数等)在整个应用程序中可能被多个模块使用。配置管理器通常使用单例模式,确保所有模块都访问同一个配置实例,而不是每次都重新加载配置文件。
作用:
- 确保唯一性:只有一个配置管理器实例,避免了重复加载配置文件的资源浪费。
- 全局访问:提供全局访问点,允许各个模块获取配置数据而无需重新读取文件或数据库。
- 提高性能:减少重复读取配置文件的次数,提升系统性能。
3.4. 线程池管理(线程池创建)
场景:线程池用于管理线程的创建、销毁和复用,确保在多线程环境下能够合理使用系统资源。线程池通常实现为单例模式,以确保全局只有一个线程池实例来处理所有任务。
作用:
- 确保唯一性:整个系统共享同一个线程池实例,避免了多个线程池对象造成的资源浪费。
- 线程管理:通过线程池集中管理线程,避免了每次任务执行时都创建新线程的开销。
- 提升性能:通过复用线程,提高了任务执行效率,减少了频繁创建和销毁线程的成本。
3.5. 缓存管理(Redis配置类)
场景:在一些高性能的应用中,经常使用缓存来存储频繁访问的数据。缓存系统(例如 Redis 缓存管理器)通常会实现为单例模式,以确保整个应用中只有一个缓存实例,所有组件都能共享同一个缓存。
作用:
- 确保唯一性:通过单例模式,缓存系统只有一个实例,避免了多个实例占用多余的内存。
- 全局共享:多个模块可以访问同一个缓存实例,提高缓存命中率,减少重复计算。
- 性能优化:缓存数据减少了对数据库或其他资源的访问,提高了系统性能。
3.6. 事件分发系统
场景:在一些事件驱动的系统中,可能会有一个全局的事件分发系统,用来管理和分发各个组件之间的事件通知。此时,可以使用单例模式来确保事件分发系统在整个应用中只有一个实例。
作用:
- 确保唯一性:确保事件分发系统只会有一个实例,避免了事件处理混乱和资源浪费。
- 全局访问:允许所有模块通过单一的事件分发器进行事件的发布和监听,确保事件流的一致性。
- 高效管理:集中管理事件,提高了系统的可维护性和扩展性。
3.7. 应用程序状态管理
场景:在一些需要跟踪全局应用状态的系统中(例如,用户登录状态、权限管理等),可以使用单例模式来管理应用程序的全局状态。
作用:
- 确保唯一性:保证全局状态管理只有一个实例,避免多个状态实例导致的不一致性。
- 简化管理:通过单一实例,简化应用状态的管理和共享,减少了不同模块之间的状态同步问题。
- 提高一致性:通过集中管理应用状态,保证整个系统的状态一致性。
4. 单例设计模式的示例(Spring)
public class MyLogUtil {public static void debug(Logger logger, String message) {debug(logger, message, (Object[])null);}public static void debug(Logger logger, String message, Object... params) {if (logger != null && logger.isDebugEnabled()) {logger.debug(getLogString(message, params));}}public static void info(Logger logger, String message) {info(logger, message, (Object[])null);}
public abstract class CollectBaseHandler<T> implements CollectService<T>, InitializingBean {private static final Logger logger = LoggerFactory.getLogger(FeatureCollectBaseHandler.class);}
public void dataSourceCollect(DecisionSessionContext sessionContext, FeatureContext featureContext) {try {LogUtil.info(logger, "”);} catch (HyxfException he){LogUtil.error(logger, "");}}
博文参考
《软件设计模式》
相关文章:
设计模式——Singleton(单例)设计模式
摘要 本文介绍了单例设计模式的概念、实现和应用场景。单例模式确保某个类只有一个实例,节省资源并提供全局访问点。文章详细解释了单例模式的实现要素,包括私有构造方法、静态实例和公共静态方法,并探讨了其在数据库连接池、日志记录器和配…...
深入理解 CSS 文本换行: overflow-wrap 和 word-break
前言 正常情况下,在固定宽度的盒子中的中文会自动换行。但是,当遇到非常长的英文单词或者很长的 URL 时,文本可能就不会自动换行,而会溢出所在容器。幸运的是,CSS 为我们提供了一些和文本换行相关的属性;今…...
Java-27 深入浅出 Spring - 实现简易Ioc-03 在上节的业务下手动实现IoC
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
kubernetes学习-使用metrics-server监控集群资源和查看日志
kubernetes学习-使用metrics-server监控集群资源和查看日志 一 、简介二、应用场景三、部署四、查看日志 一 、简介 Metrics Server 是一个用于 Kubernetes 集群的监控工具,它用于收集、存储和提供关于集群中各种资源的度量数据。Metrics Server 是 Kubernetes 中一…...
解决 Git Permission denied 问题
前言 push项目时出现gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository exists.出现这个问题表示你在尝试将本地代码推送到GitHub时,没有提供…...
CCNP_SEC_ASA 第三天作业
实验需求: ASA 使用列表放行 Outside 路由器到 DMZ 路由器的 WWW 流量并拒绝 Telnet 流量,当放行和拒绝流量匹配后产生日志通告。 提示:需要使能 ASA的日志功能和 DMZ路由器的 HTTP功能。 设备配置: ##此处展示各设备的配置&am…...
TypeError: Cannot read properties of null (reading ‘ce‘)
vue项目本地跑不起来,但是build之后能运行,本地报错 是因为你的vue版本不对,你的package可能是这样写的 这个表示你允许你的npm安装vue3的任意版本,但是build是按照这个版本来的,所以build之后能运行,本地运…...
AdminJS - 集成 MySQL 的现代化管理面板开发指南
AdminJS - 集成 MySQL 的现代化管理面板开发指南 MySQL 集成配置 首先需要安装必要的依赖: npm install adminjs adminjs/express express npm install adminjs/sequelize sequelize mysql2基础配置示例 const AdminJS require(adminjs) const AdminJSExpress …...
上传文件(vue3)
使用el-upload 先上传到文件服务器,生成url 然后点击确定按钮: 保存数据 <template><el-dialog top"48px" width"500" title"新增协议" :modelValue"visible" close"handleClose()">…...
【Win10 环境vscode配置boost】
文章目录 Boost exe版本windows环境安装vscode配置安装测试总结 Boost exe版本windows环境安装 这里不介绍boost源码安装,请自行网络搜索。本文要介绍的是window下单c文件(cpp),调用boost库的执行配置。不涉及多文件。 安装文件下…...
中间件 redis安装
redis官网地址:Redis - The Real-time Data Platform 环境 CentOS Linux release 7.9.2009 (Core) java version "17.0.12" 2024-07-16 LTS 1、通过压缩包安装redis 1,远程下载redis压缩包,或去官网下载:Downloads …...
[java] 简单的熔断器scala语言案例
failureRateInterval时间内如果addEx(错误)达到 maxFailuresPerInterval 次数,则fused方法返回true,表示触发熔断,进入冷却期coolingInterval,冷却期内fused方法返回true,冷却期过后进入下一个错误统计周期。 scala语言完成 imp…...
【java】序列化的种类和使用场景
文章目录 序列化概述什么是序列化?序列化的作用 Java内置序列化java.io.Serializable接口使用ObjectOutputStream和ObjectInputStream优缺点分析 自定义序列化实现Externalizable接口自定义序列化方法适用场景 第三方序列化框架KryoProtobuf (Google Protocol Buffe…...
Qt5与Qt6中的高DPI缩放属性解析
在Qt5中,高DPI缩放默认是禁用的。为了启用它,开发者需要设置Qt::AA_EnableHighDpiScaling应用程序属性。然而,在Qt6中,高DPI缩放默认是启用的,并且不能被禁用。这种变化使得开发者在处理高分辨率屏幕时更加方便&#x…...
Mac使用总结
Mac 常用快捷键 复制:Cmdc粘贴:Cmdv只粘贴文档: ShiftCmdv行首: Cmd<行尾:Cmd>鼠标处选中到行首:ShiftCmd<鼠标处选中到行尾:ShiftCmd>选中整行:上面两个命令组合鼠标处…...
【日期规则】EXCEl 自定义日期匹配规则,学习基础知识,自由匹配场景
excel 新建规则工具路径:开始 - 条件格式 - 新建规则 B$1TODAY() 注意:新建规则后,要点击 条件格式 - 管理规则 - 应用于 要选择规则应用范围 使用场景: excel 做进度管理当中可以查看当天的情况;每周的学习规划 或…...
苹果电脑可以安装windows操作系统吗?Mac OS X/OS X/macOS傻傻分不清?macOS系统的Java支持?什么是macOS的五大API法王?
苹果电脑可以安装windows操作系统吗? 先抛开虚拟机安装,苹果电脑可以安装Windows操作系统。苹果公司提供了一个名为Boot Camp的软件,它允许用户在Mac电脑上安装Windows操作系统。通过Boot Camp,用户可以在启动电脑时选择是要进入macOS还是Wi…...
芋道SpringBoot配置Maven、创建SpringBoot项目、创建Web接口、读取配置信息
🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列文章目录 第一章 芋…...
物理机内网穿透
前言: 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一,什么是内网穿透。 大多数情况下,我们的个人电脑都处于内网,即没有可公开访问的独立 IP 地址,因此其他内网用户找不到…...
Vue 3: 通过图片链接获取图片颜色,间接设置背景颜色
在现代Web开发中,动态获取和处理图像数据是一个常见的需求。例如,你可能希望自动提取一张图片的主色调,以便根据这些颜色进行UI主题调整或其他视觉效果的处理。本文将介绍如何在Vue 3项目中,通过一个图片链接获取图片的颜色信息。…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
