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

04_23 种设计模式之《单例模式》

文章目录

    • 一、单例模式基础知识
      • 单例模式有 3 个特点:
    • 单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种模式通常用于管理共享资源,如数据库连接、配置文件、日志记录等。
      • 单例模式的结构
    • C++实现单例模式
      • 线程安全的单例模式
      • 单例模式的应用场景
      • 注意事项
    • 懒汉模式和饿汉模式是单例模式的两种实现方式,它们在创建单例对象的时机上有所不同。
      • 饿汉模式(Eager Initialization)
      • 懒汉模式(Lazy Initialization)
        • 测试

一、单例模式基础知识

单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
单例模式是一种常用的软件设计模式。 在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

单例模式有 3 个特点:

单例类只有一个实例对象;
单例类必须自己创建自己的唯一实例;
单例类对外提供一个访问该单例的全局访问点。

主要解决:全局使用的类频繁地创建与销毁。
优点:避免对资源的多重占用。在内存里只有一个实例,减少内存的开销,尤其是频繁的创建和销毁实例。

单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种模式通常用于管理共享资源,如数据库连接、配置文件、日志记录等。

单例模式的结构

单例模式通常包含以下元素:

  1. 单例类(Singleton):包含一个实例化的自身引用,以及一个静态私有方法来获取这个实例。
  2. 客户端:通过单例类提供的静态方法获取单例对象的引用。

C++实现单例模式

在C++中实现单例模式需要考虑线程安全性和延迟初始化的问题。

#include <iostream>class Singleton {
private:static Singleton* instance;Singleton() {} // 私有构造函数// 禁止拷贝和赋值操作Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton* getInstance() {if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Doing something..." << std::endl;}
};// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;int main() {Singleton* s1 = Singleton::getInstance();s1->doSomething();Singleton* s2 = Singleton::getInstance();s2->doSomething();// s1 和 s2 是同一个实例return 0;
}

线程安全的单例模式

在多线程环境中,需要确保只有一个线程可以创建单例实例。以下是一个线程安全的单例模式实现:

#include <iostream>
#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mutex;Singleton() {} // 私有构造函数// 禁止拷贝和赋值操作Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:static Singleton* getInstance() {std::lock_guard<std::mutex> lock(mutex);if (instance == nullptr) {instance = new Singleton();}return instance;}void doSomething() {std::cout << "Doing something..." << std::endl;}
};// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;int main() {Singleton* s1 = Singleton::getInstance();s1->doSomething();Singleton* s2 = Singleton::getInstance();s2->doSomething();// s1 和 s2 是同一个实例return 0;
}

单例模式的应用场景

  1. 日志记录:整个应用程序可能需要一个共享的日志记录器。
  2. 配置管理:应用程序可能需要读取一次配置信息,并在整个应用程序中使用。
  3. 网络连接:创建一个全局的网络连接管理器,用于管理所有的网络请求。
  4. 线程池:一个应用程序可能只需要一个线程池实例来管理所有的后台任务。

注意事项

  • 全局状态:过度使用单例模式可能导致全局状态管理困难,难以测试和维护。
  • 延迟初始化:在某些情况下,可能希望延迟单例实例的创建,直到实际需要时才初始化。
  • 销毁问题:需要确保单例实例在应用程序结束时能够正确销毁,避免内存泄漏。

懒汉模式和饿汉模式是单例模式的两种实现方式,它们在创建单例对象的时机上有所不同。

饿汉模式(Eager Initialization)

饿汉模式在类加载时就立即初始化,创建单例对象。这种方式的缺点是不管是否使用这个单例,都会创建实例,可能导致资源浪费

特点

  1. 类加载时就立即初始化,创建单例对象。
  2. 不需要加锁同步,实例的创建线程安全。
  3. 实例的创建时机早,可能会造成资源浪费。

实现示例

class Singleton {
private:static Singleton* instance;Singleton() {}public:Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static Singleton* getInstance() {return instance;}// 其他成员函数...
};// 在类外部初始化静态成员变量
Singleton* Singleton::instance = new Singleton();

懒汉模式(Lazy Initialization)

懒汉模式在第一次使用单例对象时才创建实例,这样可以延迟对象的创建,节省资源。但是,它需要处理多线程环境下的线程安全问题。

特点

  1. 按需创建,只有在真正需要的时候才创建实例。
  2. 需要加锁同步,确保线程安全。
  3. 实例的创建时机晚,节省资源,但可能影响性能。

实现示例

#include <mutex>class Singleton {
private:static Singleton* instance;static std::mutex mutex;Singleton() {}public:Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static Singleton* getInstance() {std::lock_guard<std::mutex> lock(mutex);if (instance == nullptr) {instance = new Singleton();}return instance;}// 其他成员函数...
};// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

在实际应用中,选择哪种模式取决于具体的需求和场景。如果单例的实例化代价较大,且不太可能造成资源浪费,可以选择饿汉模式。如果需要更灵活地控制实例的创建时机,或者实例化代价较小,可以选择懒汉模式。

测试
void TestFunction1() {Singleton* pobj1 = Singleton::GetInstance();Singleton* pobj2 = Singleton::GetInstance();if (pobj1 == pobj2){cout << "pobj1和pobj2两个指针指向同一块内存单元:则为单例模式." << endl;}else{cout << "pobj1和pobj2两个指针指向不是同一块内存单元:不是单例模式." << endl;}
}

相关文章:

04_23 种设计模式之《单例模式》

文章目录 一、单例模式基础知识单例模式有 3 个特点&#xff1a; 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取这个实例。这种模式通常用于管理共享资源&#xff0c;如…...

视频加字幕用什么软件最快?12款工具快速添加字幕!

对于大多数同学来讲&#xff0c;剪辑中比较头疼的就是如何给视频加字幕和唱词啦&#xff0c;特别是用Pr或者FCXP等专业剪辑软件&#xff0c;加字幕也是特别费时的&#xff0c;哪怕是有批量添加的功能orz... 虽然关于这方面的内容已经很多啦&#xff0c;但是真正全面的内容还特…...

C++:string (用法篇)

文章目录 前言一、string 是什么&#xff1f;二、C语法补充1. auto2. 范围for 三、string类对象的常见构造1. Construct string object2. String destructor3. operator 四、string迭代器相关1. begin与end1&#xff09;begin2&#xff09;end3&#xff09;使用 2. rbegin 与 r…...

力扣随机题

最接近原点的K个点 题目 973. 最接近原点的 K 个点 - 力扣&#xff08;LeetCode&#xff09; 思路 这就是一道排序题&#xff0c;直接根据公式排序&#xff0c;然后返回对应范围的数组就行了 代码 public int[][] kClosest(int[][] points, int k) {Arrays.sort(points, n…...

CSS样式基础样式选择器(案例+代码实现+效果图)

目录 1.css样式的规则 2.引入css样式的方式 1)行内式 2)内嵌式 3)外链式 1-link导入 2-import导入 4)总 3.css基础选择器 1)标签选择器 案例&#xff1a;使用标签选择器编写一个圆 1.代码 2.效果 2)类选择器 案例&#xff1a;使用类选择器为div添加背景色 1.代码 2.效果 3)id…...

Linux系统编程—I/O缓冲区(C语言实现)

I/O缓冲区 进程的I/O缓冲区机制是计算机操作系统中一个重要的概念&#xff0c;它涉及到数据在内存和外设之间的传输。以下是关于进程的I/O缓冲区机制的详细解释&#xff1a; 1.定义与作用 定义&#xff1a;I/O缓冲区是指在内存里开辟的一块区域&#xff0c;用来存放接收用户输…...

MySQL多表查询:行子查询

先看我的表数据 dept表 emp表 行子查询 子查询返回的结果是一行&#xff08;可以是多列&#xff09;, 这种子查询称为行子查询 常用的操作符: , <>, IN, NOT IN 例子1. 查询与“张无忌” 的薪资及直属领导相同的员工信息 拆解成两个问题 a. 查询"张无忌"…...

.NET CORE程序发布IIS后报错误 500.19

发布IIS后浏览时报错误500.19&#xff0c;同时配置文件web.config的路径中也存在问号“?”。 可能原因&#xff1a;没有安装运行时...

Qt 6 相比 Qt 5 的主要提升与更新

自从 Qt 6 发布以来&#xff0c;作为 Qt 框架的一个重大版本更新&#xff0c;它在多个核心方面进行了深度优化和改进。与 Qt 5 相比&#xff0c;Qt 6 不仅提升了性能&#xff0c;还改进了对现代硬件和图形 API 的支持&#xff0c;并增强了开发者的工作流程。本文将详细介绍 Qt …...

【数据结构】介绍

介绍数据结构 数据结构是计算机科学中重要的概念&#xff0c;是指组织和管理数据的方式。它涉及到数据的存储、操作和访问等操作。数据结构可以分为线性结构、树形结构和图形结构等。 线性结构是最简单的数据结构之一(本玄也是这样觉得(*&#xffe3;▽&#xffe3;*))&#…...

论医疗类系统全国运营推广策略

一、线上推广 搜索引擎优化&#xff08;SEO&#xff09;- 重点策略 持续更新网站内容&#xff0c;包括系统功能介绍、成功案例、行业新闻等&#xff0c;提高网站的权重和流量。进行搜索引擎优化&#xff08;SEO&#xff09;&#xff0c;确定与医疗机构辅助系统相关的关键词&a…...

Redis入门第一步:认识Redis与快速安装配置

认识Redis与快速安装配置&#x1f343; Redis是什么&#x1f432; 1.Redis的背景&#x1f38d; Redis&#xff08;Remote Dictionary Server&#xff09;译为"远程字典服务"&#xff0c;它是一款基于内存实现的键值型 NoSQL 数据库&#xff0c; 通常也被称为数据结…...

ES postman操作全量修改,局部修改,删除

全量修改 修改需要调用的url 地址是http://192.168.1.108:9200/shopping/_doc/1001&#xff0c;调用方法使用put 只修改指定的需求的内容的请求方式 post方式就是局部修改 http://192.168.1.108:9200/shopping/_update/1001&#xff0c;请求方式post 上图是只修改id 为1001数…...

社区交流礼仪 | 提问的艺术

唠唠闲话 2021 年通过 Julia 社区了解到开源&#xff0c;自此开始融入开源社区&#xff0c;学习和体验这种独特的协作模式与交流文化&#xff0c;受益良多。本篇文章为开源新手必读&#xff0c;文章中探讨的交流模式&#xff0c;不仅对参与开源项目的协作有所帮助&#xff0c;…...

极客兔兔Gee-Cache Day5

HTTPPool 既可以是服务端&#xff0c;也可以是客户端&#xff0c;这取决于特定的使用场景和上下文&#xff1a; 作为客户端&#xff1a;当本地缓存没有找到需要的数据时&#xff0c;HTTPPool 需要作为客户端&#xff0c;通过 httpGetter &#xff08;实现了 PeerGetter 接口&am…...

【IPv6】IPv6地址格式及地址分类(组播、单播、任播)整理

IPv6地址格式 IPv6 地址从 IPv4 地址的 32 bits 扩展到 128 bits&#xff0c;IPv6 地址的表示、书写方式也从 IPv4 的点分十进制&#xff0c;修改16进制的冒号分割 IPv4 点分格式(.) 192.168.11.11 IPv6 冒号分割(:) 2408:8459:3032:0000:0000:0000:0001:a9fd IPv6 的规范…...

Linux数据备份

1、Linux服务器中哪些数据需要备份 1&#xff09;Linux系统重要数据&#xff1a; ①/root/目录&#xff0c;管理员家目录 ②/home/目录&#xff0c;普通用户家目录 ③/etc/目录 &#xff0c;系统重要的配置文件保存目录 2&#xff09;安装服务的数据&#xff1a;例apache①…...

回到原点再出发

原文What Goes Around Comes Around作者Michael Stonebraker & Joseph M. Hellerstein其他译文https://zhuanlan.zhihu.com/p/111322429 1. 摘要 本文总结了近35年来的数据模型方案&#xff0c;分成9个不同的时代&#xff0c;讨论了每个时代的方案。我们指出&#xff0c;…...

SimpleFoc以及SVPWM学习补充记录

SimpleFoc SimpleFOC移植STM32&#xff08;一&#xff09;—— 简介 FOC控制的过程是这样的&#xff1a; 对电机三相电流进行采样得到 Ia,Ib,Ic。将 Ia,Ib,Ic 经过Clark变换得到 I_alpha I_beta。将 I_alpha I_beta 经过Park变换得到 Id,Iq。计算 Id,Iq 和其设定值 Id_ref 和…...

免费 Oracle 各版本 离线帮助使用和介绍

文章目录 Oracle 各版本 离线帮助使用和介绍概要在线帮助下载离线文档包&#xff1a;解压离线文档&#xff1a;访问离线文档&#xff1a;导航使用&#xff1a;目录介绍Install and Upgrade&#xff08;安装和升级&#xff09;&#xff1a;Administration&#xff08;管理&#…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...