设计模式--单例模式(Singleton Pattern)
一、什么是单例模式
单例模式是一种创建型设计模式,它旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式限制了类的实例化次数为一个,并提供一种在应用程序中共享一个实例的方式。这对于需要只有一个实例来管理某些资源或状态的情况非常有用。
单例模式通常涉及以下几个核心概念:
- 私有构造函数(Private Constructor):单例类的构造函数被声明为私有,这意味着外部无法直接通过构造函数来创建类的实例。
- 静态成员变量(Static Member Variable):单例类通常会包含一个静态成员变量,用于保存唯一的实例。
- 静态成员函数(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;
}
三、使用单例模式需要注意的问题
使用单例模式时需要注意以下几点:
- 线程安全性:如果在多线程环境中使用单例模式,确保实现线程安全,以防止多个线程同时创建实例。可以使用互斥锁、双检锁等方法来保证线程安全。
- 延迟实例化:单例模式通常在第一次使用时创建实例。如果实例化过早,可能会造成资源浪费。只有在需要时才创建实例,这种延迟实例化的方式可以提高性能和效率。
- 内存泄漏:由于单例模式的实例在整个应用程序生命周期内存在,如果不适当地管理实例,可能会导致内存泄漏。在程序结束时,应该正确地销毁实例。
- 全局状态:由于单例模式提供了全局访问点,可能导致过度使用全局状态。过多地使用全局状态可能会导致代码难以维护,因此应该谨慎使用单例模式。
- 单一职责原则:尽量确保单例类只负责管理单一的实例,而不应该涉及过多的业务逻辑。将不同的功能拆分到不同的类中,以遵循单一职责原则。
- 反射和序列化:一些编程语言和环境支持反射和序列化,这可能会破坏单例模式。为了避免这种情况,可以通过禁用类的克隆、序列化等方式来保护单例的独特性。
- 测试难度:由于单例模式的全局状态,可能会导致测试变得困难,因为在不同的测试用例之间共享状态可能会产生副作用。为了更好地进行单元测试,可以使用依赖注入等技术。
总之,单例模式在适当的情况下是非常有用的,但也需要谨慎使用,以避免潜在的问题和复杂性。了解单例模式的优缺点,并根据具体情况来决定是否使用它。

相关文章:
设计模式--单例模式(Singleton Pattern)
一、什么是单例模式 单例模式是一种创建型设计模式,它旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。换句话说,单例模式限制了类的实例化次数为一个,并提供一种在应用程序中共享一个实例的方式。这对于需要只有…...
postgis数据库从一张表中过滤出一部分数据到新表中
你可以使用以下步骤在PostGIS数据库中过滤objectid<100的数据,并将其创建为新表:打开PostGIS数据库的终端或客户端工具(如Psql)。 选择你要过滤数据的表。假设表名为"original_table",该表包含一个名为&q…...
INDEMIND:“大+小”多机协同,实现机器人商用场景全覆盖
随着商用清洁机器人进入越来越多的场景中,单一的中型机器人并不能有效覆盖所有区域,更加细分化的产品组合正在成为新的趋势。 产品形态的“新趋势” 在商用场景中,目前的商用清洁机器人几乎均是中大型的产品形态,较大的体型意味…...
微信开发之一键创建标签的技术实现
简要描述: 添加标签 请求URL: http://域名地址/addContactLabel 请求方式: POST 请求头Headers: Content-Type:application/jsonAuthorization:login接口返回 参数: 参数名必选类型说明…...
八一参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022.
八一参考文献:[八一新书]许少辉.乡村振兴战略下传统村落文化旅游设计[M]北京:中国建筑出版传媒,2022....
ChatGPT⼊门到精通(7):GPT3.5与 4.0区别
⼀、详细区别 1 项⽬ GPT3.5 GPT4.0 2 打字速度 较慢,⾼峰期更慢 更加慢,差别不⼤ 3 掉线⼏率 经常掉线 很少掉线 4 分段能⼒ ⽣成⼏百字后就停⽌了, 需要回复“继续”,有时候不 是很连贯 基本连贯 5 使⽤限制 1⼩时100次提问&am…...
Springboot整合MyBatisPlus框架操作MySQL
1、MyBatis-Plus概述 MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 【技术储备】 拥有 Java 开发环境以及相应 IDE…...
基于Jenkins构建生产CICD环境(第二篇)
基于Jenkins自动打包并部署Tomcat环境 传统网站部署的流程 在运维过程中,网站部署是运维的工作之一。传统的网站部署的流程大致分为:需求分 析-->原型设计-->开发代码-->提交代码-->内网部署-->内网测试-->确认上线-->备份数据-->外网更新…...
ioctl、printk及多个此设备支持
一、ioctl操作实现 ioctl(Input/Output Control)是一个在 Unix-like 操作系统中的系统调用,用于控制设备或文件的各种操作。它允许用户空间程序与内核空间进行交互,执行一些特定的设备控制、状态查询或其他操作,而不必…...
电脑每次开机杀毒软件报iusb3mon.exe病毒已清除,电脑中病毒iusbmon杀毒办法,工具杀毒
不知道什么时候开始,我电脑C盘的系统数据存储文件夹programdata 不知不觉就没了,找不到了 programdata文件夹为存储系统数据文件的,这个文件不见了,而且我打开了显示隐藏文件和文件夹还是没有显示 然后我重启电脑,杀毒…...
centos服务器系统下安装python3并与自带的python2
centos服务器系统下安装python3并与自带的python2 在centos中,自带有python2,因此需要经常安装python3。但是这里有一个坑,就是centos的yum是用python2写的,如果正常编译安装python3,那么yum就会直接挂了。为了方便以…...
(二十)大数据实战——Flume数据采集的基本案例实战
前言 本节内容我们主要介绍几个Flume数据采集的基本案例,包括监控端口数据、实时监控单个追加文件、实时监控目录下多个新文件、实时监控目录下的多个追加文件等案例。完成flume数据监控的基本使用。 正文 监控端口数据 ①需求说明 - 使用 Flume 监听一个端口&am…...
AutoCAD图如何保存为Word
AutoCAD图如何保存为Word 引言AutoCAD图保存为Word文件步骤: 引言 不知道大家有没有是否遇到需要将AutoCAD图保存到Word中。有些小伙伴可能直接截图插入Word中,这种方法简单,但对于有高清图片需求的小伙伴就不适用了。接下来我就为大家介绍一…...
Java线程 - 详解(2)
一,线程安全问题 有些代码在单个线程的环境下运行,完全正确,但是同样的代码,让多个线程去执行,此时就可能出现BUG,这就是所谓的 "线程安全问题"。举一个例子: public class Demo {s…...
事务特性 - 达梦数据库
达梦数据库事务特性 1 事务特性1.1 原子性1.2 一致性1.3 隔离性1.4 持久性 1 事务特性 事务必须具备什么属性才是一个有效的事务呢?一个逻辑工作单元必须表现出四种属性,即原子性、一致性、隔离性和持久性,这样才能成为一个有效的事务。DM 数…...
axios 使用FormData格式发送GET请求
如果你需要使用,FormData格式,发送GET请求 将参数拼接到 FormData对象 中,使用 URLSearchParams 将FormData对象转换为查询参数字符串,并将其拼接到URL中,这样就能以FormData格式发送GET请求给服务器 注意࿱…...
CS144(2023 Spring)Lab 1: stitching substrings into a byte stream
文章目录 前言其他笔记相关链接 1. Getting started2. Putting substrings in sequence2.1 需求分析2.2 注意事项2.3 代码实现 3. 测试与优化 前言 这一个Lab主要是实现一个TCP receiver的字符串接收重组部分。 其他笔记 Lab 0: networking warmup Lab 1: stitching substri…...
【PHP】常用的PHP内置函数
1、PHP内置函数非常丰富,用于执行各种任务。以下是一些常用的PHP内置函数: 字符串操作函数: strlen(): 返回字符串的长度。 strpos(): 查找字符串中的某个子串第一次出现的位置。 substr(): 返回字符串的子串。 str_replace(): 替换字符串中的…...
css自学框架之消息弹框
首先我们还是看看消息弹框效果: 主要实现代码分为三部分 一、CSS部分,这部分主要是定义样式,也就是我们看到的外表,主要代码: /* - 弹窗 */notice{top: 0;left: 0;right: 0;z-index: 10;padding: 1em;position: fix…...
42、Flink 的table api与sql之Hive Catalog
Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
