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

设计模式 - 单例模式

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快!

文章目录

      • 引言
      • 一、单例模式的基本概念
      • 二、单例模式的实现
        • 1. 懒汉式单例模式
        • 2. 饿汉式单例模式
        • 3. 双重检查锁定(DCL)单例模式
        • 4. 枚举单例模式
      • 三、单例模式的优点
      • 四、单例模式的缺点
      • 五、单例模式的应用场景
      • 六、单例模式的变种
      • 七、单例模式的实现细节
        • 1. 可序列化问题
        • 2. 防止反射攻击
      • 八、总结

引言

单例模式是一种常用的创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。这种模式对于那些需要频繁创建和销毁对象的场合非常有用,例如日志记录器、缓存管理器、数据库连接池等。本文将详细介绍单例模式的实现原理,并通过具体的Java代码示例来说明如何实现这一模式。

一、单例模式的基本概念

单例模式的核心在于确保一个类只能有一个实例,并且提供一个全局访问点来获取这个实例。通常情况下,单例模式通过以下三个步骤实现:

  1. 将构造函数声明为私有的,防止外部直接创建新实例。
  2. 提供一个静态方法或属性作为全局访问点,用于获取唯一的实例。
  3. 在静态方法或属性内部实现延迟加载,确保只有在第一次调用时才创建实例。

二、单例模式的实现

接下来,我们将通过一个示例来详细了解单例模式的实现步骤。

1. 懒汉式单例模式

懒汉式单例模式是在第一次调用时才创建实例的单例模式。这种方式的优点是按需加载,但需要同步机制来保证线程安全。

public class SingletonLazy {private static SingletonLazy instance;private SingletonLazy() {// Private constructor to prevent instantiation.}public static synchronized SingletonLazy getInstance() {if (instance == null) {instance = new SingletonLazy();}return instance;}
}
2. 饿汉式单例模式

饿汉式单例模式是在类加载时就创建实例的单例模式。这种方式的优点是线程安全,但缺点是可能会提前占用资源。

public class SingletonEager {private static final SingletonEager instance = new SingletonEager();private SingletonEager() {// Private constructor to prevent instantiation.}public static SingletonEager getInstance() {return instance;}
}
3. 双重检查锁定(DCL)单例模式

双重检查锁定(Double-Checked Locking, DCL)是一种优化后的懒汉式单例模式,它通过双重检查来避免不必要的同步开销。

public class SingletonDCL {private volatile static SingletonDCL instance;private SingletonDCL() {// Private constructor to prevent instantiation.}public static SingletonDCL getInstance() {if (instance == null) {synchronized (SingletonDCL.class) {if (instance == null) {instance = new SingletonDCL();}}}return instance;}
}
4. 枚举单例模式

枚举单例模式是 Java 中一种简洁且线程安全的实现方式。

public enum SingletonEnum {INSTANCE;public void someMethod() {// Implementation details.}
}

三、单例模式的优点

  1. 资源节约:单例模式可以保证系统内存中只存在一个实例,从而节省内存空间。
  2. 全局访问:单例模式提供了一个全局访问点,可以在整个系统中访问同一个实例。
  3. 控制实例化:单例模式限制了实例化的数量,有助于控制实例的数量。

四、单例模式的缺点

  1. 难以测试:由于单例模式破坏了依赖注入的原则,因此在单元测试时可能会遇到困难。
  2. 难以扩展:如果需要扩展单例类的功能,可能会因为单例模式的限制而变得困难。
  3. 违反单一职责原则:单例类往往承担了过多的责任,这不符合单一职责原则。

五、单例模式的应用场景

单例模式适用于以下情况:

  1. 资源管理:例如数据库连接池、线程池等。
  2. 配置管理:例如读取配置文件的类。
  3. 日志管理:例如日志记录器。

六、单例模式的变种

除了上述基本的单例模式外,还有以下一些变种:

  1. 多例模式:类似于单例模式,但允许创建多个实例。
  2. 延迟初始化的单例模式:仅在首次请求时创建实例。
  3. 线程局部单例模式:为每个线程提供一个单独的实例。

七、单例模式的实现细节

1. 可序列化问题

如果单例类实现了 Serializable 接口,那么可以通过序列化和反序列化来创建多个实例。为了避免这种情况,可以在单例类中添加一个 readResolve 方法来控制反序列化过程。

public class SerializableSingleton implements Serializable {private static final long serialVersionUID = 1L;private static final SerializableSingleton instance = new SerializableSingleton();private SerializableSingleton() {// Private constructor to prevent instantiation.}public static SerializableSingleton getInstance() {return instance;}protected Object readResolve() {return instance;}
}
2. 防止反射攻击

反射可以绕过私有构造函数,导致创建额外的实例。为了避免这种情况,可以在构造函数中加入检测机制。

public class ReflectionSingleton {private static final ReflectionSingleton instance = new ReflectionSingleton();private static final AtomicInteger counter = new AtomicInteger(0);private ReflectionSingleton() {if (counter.incrementAndGet() > 1) {throw new IllegalStateException("Cannot instantiate more than one instance!");}}public static ReflectionSingleton getInstance() {return instance;}
}

八、总结

通过本文的详细介绍和示例代码,相信你应该已经了解了单例模式的基本实现细节及其在不同情况下的表现。单例模式是面向对象设计中一种非常有用的模式,特别是在需要确保某个类只有一个实例,并且提供一个全局访问点的情况下。在实际编程中,单例模式可以用于创建高度可配置和可扩展的系统,尤其是在需要管理有限资源时。通过上述实现,你可以根据自己的需求进一步扩展和优化单例模式的应用。

单例模式虽然简单,但在设计系统时需要考虑到其潜在的问题,比如线程安全性、序列化问题等。正确地使用单例模式可以使你的代码更加健壮和易于维护。


💝💝💝如有需要请大家订阅我的专栏【设计模式】哟!我会定期更新相关系列的文章
💝💝💝关注!关注!!请关注!!!请大家关注下博主,您的支持是我不断创作的最大动力!!!

设计模式相关文章索引文章链接
设计模式 - 抽象工厂模式 设计模式 - 抽象工厂模式

❤️❤️❤️觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

相关文章:

设计模式 - 单例模式

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 引言一、单例模…...

fastapi之WebSockets

文章目录 WebSockets基本概念FastAPI 中的 WebSocket 支持WebSocket 应用示例示例 1: 简单的 WebSocket 连接解释 示例 2: 广播消息的 WebSocket 实现解释 客户端代码示例 完整示例项目结构服务器端代码 (main.py)解释 简单的前端客户端 (static/index.html)解释 测试 相关代码…...

Kotlin 和 Java区别

Kotlin 和 Java 是两种主要用于 Android 开发的编程语言,它们之间有一些关键的区别: 1. 语法简洁性: Kotlin:具有更简洁的语法,减少了冗余代码。例如,Kotlin 支持类型推断,避免了大量的样板…...

windows 达梦到ORACLE dblink

达梦通过DBLINK访问Oracle数据库有两种: 方式一:通过Oracle oci接口; 方式二:一种是通过ODBC数据源的方式。 本案例选择使用Oralce OCI的方式去访问Oracle数据库。 配置Oracle OCI客户端 下载地址:https://www.oracle.com/database/techno…...

大数据应用组件

1、数据存储1.1、hive->hdfs、mapredus1.2、ClickHouse1.3、Elasticsearch1.4、PostgreSQL1.5、HBase 2、数据抽取2.1、Kettle2.2、DataX2.3、Canal2.4、Flink CDC2.5、Sqoop2.6、Filebeat&Logstash(日志) 3、任务编排3.1、Apache DolphinScheduler 4、数据处理4.1、spa…...

Docker Remote API未授权访问漏洞

9.Docker Remote API未授权访问漏洞 步骤一:使用以下Fofa语句对Docker产品进行搜索. port"2375" 步骤二:直接使用浏览器访问以下路径 /version#查看版本信息 /info#查看容器信息 漏洞修复 1.端口访问控制 对2375端口做网络访问控制,如设置iptables…...

算法训练.

一.扩散 题解&#xff1a; 计算点之间的距离&#xff0c;然后对图进行处理即可&#xff0c;这个数据规模较小&#xff0c;因此我使用了floyd,还有最小生成树和二份答案加并查集的写法&#xff1b; 代码&#xff1a; #include <iostream> #include <cstring> #in…...

08、MySQL-事务

目录 1、事务简介 2、事务操作 2.1 方式一 2.2 方式二 3、事务四大特性 4、并发事务问题 5、事务隔离级别 1、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c…...

2024 年的 Node.js 生态系统

数据来源于 Node.js Toolbox&#xff0c;网站展示了 Node.js 生态系统中积极维护且流行的库。...

LVS(Linux Virtual Server)

简介 LVS&#xff08;Linux Virtual Server&#xff09;是一个高性能的开源负载均衡解决方案&#xff0c;它通过在Linux内核中实现IPVS&#xff08;IP Virtual Server&#xff09;模块来提供负载均衡功能。LVS能够将外部请求根据特定的算法分发到后端的多个服务器上&#xff0c…...

回顾Python

一、python基础 1、环境python2、python3 [rootpython ~]# yum list installed | grep python #检查是否有python包 [rootpython ~]# yum list installed | grep epel #检查是否有epel包 [rootpython ~]# yum -y install epel-release [rootpython ~]# yum -y install …...

【数据结构】队列,你必须知道的内部原理!!!

&#x1f31e;&#x1f31e;&#x1f31e;生活本就沉闷&#xff0c;但跑起来就会有风 ~~~ 前言&#xff1a; &#x1f31f;&#x1f31f;Hello家人们&#xff0c;这期讲解数据结构队列的基础知识&#xff0c;希望你能帮到屏幕前的你。 &#x1f4da;️上期博客在这里&#xff1…...

Ubuntu24.04编译FFmpeg6.1(支持x264、x265、fdk-acc)

FFmpeg是一个开源的多媒体处理工具集&#xff0c;可以用于处理音频、视频和图片等多种媒体格式。由于其强大的功能和灵活性&#xff0c;FFmpeg被广泛应用在多媒体处理领域&#xff0c;包括音视频编解码、流媒体服务器、视频转码等。FFmpeg7.0 版本移除了 6.0 之前已弃用的 API&…...

顺序表-数据结构

一、结构定义 顺序表是通常是数组&#xff0c;要求数据连续存储。顺序表又分为定长顺序表和变长顺序表&#xff0c;本文实现后者。 1、头文件 #include <stdio.h> #include <stdlib.h> 2、定长顺序表 #define MAX 100 定长顺序表结构 typedef struct SqList {…...

如何写出更优雅的并行程序?

如何写出更优雅的并行程序&#xff1f; 并行编程关于并行编程的一些理解 并行编程 并行编程是一种利用多个处理器或计算资源同时执行多个任务的编程方式&#xff0c;以提高计算效率和性能。允许程序员编写可以在多核处理器或多个计算机节点上同时执行的程序&#xff0c;以充分…...

C#中的Hangfire和Quartz.NET 任务调度的区别

Hangfire 和 Quartz.NET 是两种常见的 C# 任务调度库&#xff0c;它们有不同的特点和使用场景。以下是这两个库的详细对比&#xff0c;包括它们的主要功能、适用场景以及关键区别。 目录 Hangfire 主要功能 适用场景 示例代码 Quartz.NET 主要功能 适用场景 示例代码 …...

银行卡二三四要素验证-银行卡二三四要素验证接口-银行卡二三四要素

接口简介&#xff1a;全面覆盖&#xff0c;支持所有带银联标识的银行卡; 高准确性-验证结果实时返回&#xff0c;准确率达99%; 高稳定性-双通道自动切换&#xff0c;保证业务不间断; 专业服务-7*24小时服务&#xff0c;极速响应&#xff0c;为用户保驾护航; 接口地址&#xff1…...

C# 设计模式之命令模式

总目录 前言 命令模式在日常中&#xff0c;也是比较常见的&#xff0c;就比如&#xff1a;妈妈和爸爸说&#xff0c;你去让孩子把地扫一下&#xff1b;这就是是一个命令&#xff0c;命令中的 下达命令的是妈妈&#xff0c;传达命令的是爸爸&#xff0c;接受命令做事的是孩子&a…...

pod详解 list-watch机制 预选优选策略 如何指定节点调度pod

K8S是通过 list-watch 机制实现每个组件的协同工作 controller-manager、scheduler、kubelet 通过 list-watch 机制监听 apiserver 发出的事件&#xff0c;apiserver 也会监听 etcd 发出的事件 scheduler的调度策略&#xff1a; 预选策略&#xff08;Predicates&#xff09;…...

深入探索:【人工智能】、【机器学习】与【深度学习】的全景视觉之旅

目录 第一部分&#xff1a;人工智能、机器学习与深度学习概述 1.1 人工智能的概念与发展 代码示例&#xff1a;简单的AI决策系统 1.2 机器学习的定义与分类 代码示例&#xff1a;简单的线性回归模型 1.3 深度学习的基础与应用 代码示例&#xff1a;构建简单的神经网络 …...

从炸管到稳定运行:我的MOSFET应用避坑实录(附热设计、驱动电路实测数据)

从炸管到稳定运行&#xff1a;我的MOSFET应用避坑实录 去年夏天&#xff0c;当我设计的48V转12V DC-DC模块第三次在高温测试中炸毁时&#xff0c;实验室里弥漫的焦糊味终于让我意识到&#xff1a;MOSFET的应用远不是选个低Rds(on)就万事大吉。作为从业十年的电源工程师&#x…...

AI专著生成新玩法!掌握这些工具,快速产出高质量专业专著

学术专著写作挑战与 AI 辅助工具介绍 学术专著的根本价值在于其内容的系统性与内部逻辑的完整性&#xff0c;但这往往是写作中的一个重大挑战。相较于期刊论文专注于某个特定问题&#xff0c;学术专著必须构建一个包括绪论、理论框架、核心研究、应用拓展&#xff0c;以及结论…...

基于CIEDE2000标准的AI图像分层技术:从像素聚类到设计效率革命

基于CIEDE2000标准的AI图像分层技术&#xff1a;从像素聚类到设计效率革命 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 在数字设计领域&#xff0c;将…...

多进程和多线程的特点和区别

小编觉得&#xff0c;多进程和多线程的差异主要体现在以下三个方面&#xff1a; 1. 资源隔离 多线程属于同一进程&#xff0c;共享进程的堆内存和全局变量&#xff0c;因此线程间可以直接访问彼此共享的数据。但需要注意的是&#xff0c;每个线程也拥有自己私有的栈空间&…...

3步构建智能文献管理系统:Zotero GPT插件从配置到精通指南

3步构建智能文献管理系统&#xff1a;Zotero GPT插件从配置到精通指南 【免费下载链接】zotero-gpt GPT Meet Zotero. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-gpt 在信息爆炸的学术环境中&#xff0c;研究人员平均每天需要处理超过20篇文献&#xff0c;传…...

Phi-3 Forest Lab应用场景:科研人员实验设计思路启发助手

Phi-3 Forest Lab应用场景&#xff1a;科研人员实验设计思路启发助手 1. 引言&#xff1a;当科研思路遇到“森林智者” 你有没有过这样的时刻&#xff1f;面对一个全新的研究课题&#xff0c;实验方案想了三天三夜&#xff0c;却总觉得思路打不开&#xff0c;或者陷入了某个细…...

OpenClaw开源贡献指南:Qwen3.5-9B技能模块PR提交流程

OpenClaw开源贡献指南&#xff1a;Qwen3.5-9B技能模块PR提交流程 1. 为什么需要你的贡献 去年冬天&#xff0c;当我第一次尝试用OpenClaw自动整理电脑上的照片时&#xff0c;发现现有的技能库缺少一个"智能相册整理"模块。那一刻我突然意识到&#xff1a;这个开源项…...

从“无风扇散热”到“完美机房”:我与AI的一场散热与存储深度对话

本文源于我与AI的一次技术探讨&#xff0c;从无风扇散热模组的工作原理出发&#xff0c;逐步深入到浸泡式液冷、热辐射优化、算力中心架构&#xff0c;最终延伸至存储介质的可靠性对比。这是一次从“芯片级散热”到“系统级存储”的完整技术认知之旅。前言&#xff1a;一个好奇…...

LangChain串联DeepSeek时,如何用自定义OutputParser解决‘思考污染’问题?

LangChain串联DeepSeek时如何用自定义OutputParser解决"思考污染"问题 当我们在LangChain框架中串联使用具备"思考过程"输出的推理模型&#xff08;如DeepSeek&#xff09;时&#xff0c;经常会遇到一个棘手的问题&#xff1a;前序节点的思考标签会污染后续…...

AI绘画杀死UI设计师?幸存者在开发岗位的复仇

在数字技术的狂潮中&#xff0c;AI绘画工具的崛起如海啸般席卷设计行业。短短几年间&#xff0c;Midjourney、Stable Diffusion等AI平台已能10秒生成上百张海报&#xff0c;基础美工岗招聘量骤降35%&#xff0c;薪资停滞在4-6K区间。无数UI设计师面临失业危机&#xff0c;仿佛一…...