当前位置: 首页 > 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;构建简单的神经网络 …...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...