设计模式——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项目中,通过一个图片链接获取图片的颜色信息。…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
