设计模式--单例模式(Singleton Pattern)

一、什么是单例模式

单例模式是一种创建型设计模式,它旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式限制了类的实例化次数为一个,并提供一种在应用程序中共享一个实例的方式。这对于需要只有一个实例来管理某些资源或状态的情况非常有用。

单例模式通常涉及以下几个核心概念:

  1. 私有构造函数(Private Constructor):单例类的构造函数被声明为私有,这意味着外部无法直接通过构造函数来创建类的实例。
  2. 静态成员变量(Static Member Variable):单例类通常会包含一个静态成员变量,用于保存唯一的实例。
  3. 静态成员函数(Static Member Function):通过静态成员函数来获取单例实例。这个函数通常负责检查是否已经有实例存在,如果没有则创建一个新的实例,并返回该实例。

通过实现单例模式,可以确保在应用程序中只有一个全局的实例,这对于资源共享、状态管理、配置信息等情况非常有用。然而,需要注意在多线程环境下实现单例模式可能会带来线程安全的问题,因此需要采取适当的措施来确保线程安全性。

二、单例模式代码样例

当实现单例模式时,我们需要确保类只有一个实例,并且提供全局访问点来获取该实例。以下是一个用C++实现的简单单例模式的代码样例:

#include <iostream>class Singleton {
private:static Singleton* instance; // 静态成员变量,保存唯一实例Singleton() {// 私有构造函数,防止外部实例化std::cout << "Singleton instance created." << std::endl;}public:// 静态成员函数,获取单例实例static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Singleton is doing something." << std::endl;}
};Singleton* Singleton::instance = nullptr; // 初始化静态成员变量int main() {Singleton* singleton1 = Singleton::getInstance();Singleton* singleton2 = Singleton::getInstance();if (singleton1 == singleton2) {std::cout << "singleton1 and singleton2 are the same instance." << std::endl;}singleton1->doSomething();return 0;
}

在这个例子中,Singleton 类有一个私有的静态成员变量 instance 用于保存唯一实例。构造函数是私有的,这样外部无法实例化。通过静态成员函数 getInstance 来获取单例实例,如果实例不存在,则创建一个新实例。其他成员函数可以在实例上执行操作。

需要注意的是,这种简单的实现在多线程环境下可能会出现问题,因为在并发情况下可能会创建多个实例。为了确保线程安全,可以使用互斥锁或者其他同步机制。

当在单例模式中面临多线程环境时,需要确保线程安全。以下是一个使用互斥锁(mutex)来实现线程安全的单例模式样例:

#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mutex; // 互斥锁Singleton() {std::cout << "Singleton instance created." << std::endl;}public:static Singleton* getInstance() {std::lock_guard<std::mutex> lock(mutex); // 在获取实例时加锁if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Singleton is doing something." << std::endl;}
};Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex; // 初始化互斥锁int main() {Singleton* singleton1 = Singleton::getInstance();Singleton* singleton2 = Singleton::getInstance();if (singleton1 == singleton2) {std::cout << "singleton1 and singleton2 are the same instance." << std::endl;}singleton1->doSomething();return 0;
}

三、使用单例模式需要注意的问题

使用单例模式时需要注意以下几点:

  1. 线程安全性:如果在多线程环境中使用单例模式,确保实现线程安全,以防止多个线程同时创建实例。可以使用互斥锁、双检锁等方法来保证线程安全。
  2. 延迟实例化:单例模式通常在第一次使用时创建实例。如果实例化过早,可能会造成资源浪费。只有在需要时才创建实例,这种延迟实例化的方式可以提高性能和效率。
  3. 内存泄漏:由于单例模式的实例在整个应用程序生命周期内存在,如果不适当地管理实例,可能会导致内存泄漏。在程序结束时,应该正确地销毁实例。
  4. 全局状态:由于单例模式提供了全局访问点,可能导致过度使用全局状态。过多地使用全局状态可能会导致代码难以维护,因此应该谨慎使用单例模式。
  5. 单一职责原则:尽量确保单例类只负责管理单一的实例,而不应该涉及过多的业务逻辑。将不同的功能拆分到不同的类中,以遵循单一职责原则。
  6. 反射和序列化:一些编程语言和环境支持反射和序列化,这可能会破坏单例模式。为了避免这种情况,可以通过禁用类的克隆、序列化等方式来保护单例的独特性。
  7. 测试难度:由于单例模式的全局状态,可能会导致测试变得困难,因为在不同的测试用例之间共享状态可能会产生副作用。为了更好地进行单元测试,可以使用依赖注入等技术。

总之,单例模式在适当的情况下是非常有用的,但也需要谨慎使用,以避免潜在的问题和复杂性。了解单例模式的优缺点,并根据具体情况来决定是否使用它。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/55249.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统编程:线程控制

目录 一. 线程的创建 1.1 pthread_create函数 1.2 线程id的本质 二. 多线程中的异常和程序替换 2.1 多线程程序异常 2.2 多线程中的程序替换 三. 线程等待 四. 线程的终止和分离 4.1 线程函数return 4.2 线程取消 pthread_cancel 4.3 线程退出 pthread_exit 4.4 线程…

Day44|leetcode 518.零钱兑换II、377. 组合总和 Ⅳ

完全背包理论基础 视频链接&#xff1a;带你学透完全背包问题&#xff01; 和 01背包有什么差别&#xff1f;遍历顺序上有什么讲究&#xff1f;_哔哩哔哩_bilibili 完全背包与01背包不同的地方就是&#xff1a;01背包每种物品只能取一次&#xff0c;而完全背包每种物品可以取…

2023年国赛数学建模思路 - 案例:粒子群算法

文章目录 1 什么是粒子群算法&#xff1f;2 举个例子3 还是一个例子算法流程算法实现建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Pa…

yolov5中添加ShuffleAttention注意力机制

ShuffleAttention注意力机制简介 关于ShuffleAttention注意力机制的原理这里不再详细解释.论文参考如下链接here   yolov5中添加注意力机制 注意力机制分为接收通道数和不接受通道数两种。这次属于接受通道数注意力机制,这种注意力机制由于有通道数要求,所示我们添加的时候…

学习JAVA打卡第四十四天

Scanner类 ⑴Scanner对象 scanner对象可以解析字符序列中的单词。 例如&#xff1a;对于string对象NBA 为了解析出NBA的字符序列中的单词&#xff0c;可以如下构造一个scanner对象。 将正则表达式作为分隔标记&#xff0c;即让scanner对象在解析操作时把与正则表达式匹配的字…

【Linux】多线程概念线程控制

文章目录 多线程概念Linux下进程和线程的关系pid本质上是轻量级进程id&#xff0c;换句话说&#xff0c;就是线程IDLinux内核是如何创建一个线程的线程的共享和独有线程的优缺点 线程控制POSIX线程库线程创建线程终止线程等待线程分离 多线程概念 Linux下进程和线程的关系 在…

使用StreamLold写入 Starrocks报错:Caused by org

问题描述 使用StreamLoad写入Starrocks报错&#xff0c;报这个错误:Caused by: org.apache.http.ProtocolException: Content-Length header already present 代码案例 引入依赖 <!-- Starrocks使用StreamLoad发送Http请求 --><dependency><groupId>or…

系统架构设计高级技能 · 面向服务架构设计理论与实践

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…

【自动驾驶】TI SK-TDA4VM 开发板上电调试,AI Demo运行

1. 设备清单 TDA4VM Edge AI 入门套件【略】USB 摄像头(任何符合 V4L2 标准的 1MP/2MP 摄像头,例如:罗技 C270/C920/C922)全高清 eDP/HDMI 显示屏最低 16GB 高性能 SD 卡连接到互联网的 100Base-T 以太网电缆【略】UART电缆外部电源或电源附件要求: 标称输出电压:5-20VDC…

Jmeter 接口测试总结

背景介绍 对于 Android 项目来说&#xff0c;使用的是 Java 开发&#xff0c;网络请求接口的数量庞大且复杂&#xff0c;测试人员无法很直观的判断、得出网络请求是否存在问题。另一方面&#xff0c;为了验证请求接口是否能够在大负荷条件下&#xff0c;长时间、稳定、正常的运…

【JMeter】常用线程组设置策略

目录 一、前言 二、单场景基准测试 1.介绍 2.线程组设计 3.测试结果 三、单场景并发测试 1.介绍 2.线程组设计 3.测试结果 四、单场景容量/爬坡测试 1.介绍 2.线程组设计 3.测试结果 五、混合场景容量/并发测试 1.介绍 六、稳定性测试 1.介绍 2.线程组设计 …

C++中的const成员变量和成员函数

在类中&#xff0c;如果你不希望某些数据被修改&#xff0c;可以使用const关键字加以限定。const 可以用来修饰成员变量和成员函数。 const成员变量 const 成员变量的用法和普通 const 变量的用法相似&#xff0c;只需要在声明时加上 const 关键字。初始化 const 成员变量只有…

深度学习优化入门:Momentum、RMSProp 和 Adam

目录 深度学习优化入门&#xff1a;Momentum、RMSProp 和 Adam 病态曲率 1牛顿法 2 Momentum:动量 3Adam 深度学习优化入门&#xff1a;Momentum、RMSProp 和 Adam 本文&#xff0c;我们讨论一个困扰神经网络训练的问题&#xff0c;病态曲率。 虽然局部极小值和鞍点会阻碍…

01-jupyter notebook的使用方法

一、Tab补全 在shell中输入表达式&#xff0c;按下Tab&#xff0c;会搜索已输入变量&#xff08;对象、函数等等&#xff09;的命名空间&#xff1a; 除了补全命名、对象和模块属性&#xff0c;Tab还可以补全其它的。当输入看似文件路径时 &#xff08;即使是Python字符串&…

文心一言 VS 讯飞星火 VS chatgpt (79)-- 算法导论7.4 4题

四、请用go语言&#xff0c;证明:RANDOMIZED-QUICKSORT 期望运行时间是 Ω(nlgn)。 文心一言&#xff1a; 首先&#xff0c;为了证明RANDOMIZED-QUICKSORT的期望运行时间是Ω(nlg n)&#xff0c;我们需要证明在最坏的情况下&#xff0c;该算法的运行时间是O(nlg n)。然后&…

网络:RIP协议

1. RIP协议原理介绍 RIP是一种比较简单的内部网关协议&#xff08;IGP协议&#xff09;&#xff0c;RIP基于距离矢量的贝尔曼-福特算法(Bellman - Ford)来计算到达目的网络的最佳路径。最初的RIP协议开发时间较早&#xff0c;所以在带宽、配置和管理方面的要求也较低。 路由器运…

dockerfile镜像及Harbor私有仓库搭建的应用

目录 搭建私有仓库harbordockerfile构建镜像1&#xff0c;先创建一个目录2&#xff0c;编写dockerfile3&#xff0c;构建4&#xff0c; 验证镜像5&#xff0c;标记镜像6&#xff0c;上传镜像 搭建私有仓库harbor 首先安装容器编排工具&#xff1a;docker compose 我使用的是离…

信创国产系统麒麟arm架构中nginx安装过程

前言 在事业单位或国企&#xff0c;信创项目在步步推进&#xff0c;下面将在国产系统通信arm架构中nginx的安装过程记录分享出来&#xff0c;希望帮助到有需要的小伙伴。 1、nginx下载 1.1、在线下载 进入指定目录&#xff0c;如/usr/local&#xff0c;执行如下命令&#x…

LoRA继任者ReLoRA登场,通过叠加多个低秩更新矩阵实现更高效大模型训练效果

论文链接&#xff1a; https://arxiv.org/abs/2307.05695 代码仓库&#xff1a; https://github.com/guitaricet/peft_pretraining 一段时间以来&#xff0c;大模型&#xff08;LLMs&#xff09;社区的研究人员开始关注于如何降低训练、微调和推理LLMs所需要的庞大算力&#xf…