创建型模式——单例(singleton)
1. 模式说明
单例模式保证类只有一个实例;创建一个对象,当你创建第二个对象的时候,此时你获取到的是已经创建过的对象,而不是一个新的对象;
1.1 使用场景
共享资源的访问权限;任务的管理类;数据库的操作等;
1.2 要素
- 私有化类的构造函数;
- 使用类的私有静态指针变量指向类的唯一实例
- 公有静态方法获取该实例;
1.3 类型
- 懒汉模式
- 饿汉模式
2. 懒汉模式
单例实例在第一次被使用时才进行初始化,延迟初始化
2.1 基本
示例
/** @brief : design patterns singleton* @author : your name* @compile : g++ -g singleton_main.cc -o d -std=c++11* @date : 2023/04/18* @lastEditorDate: */#include <iostream>
#include <string>//懒汉模式
class Singleton
{
public:static Singleton* getSingletonInstance() //访问函数{if(instance == nullptr){instance = new Singleton;}return instance;}public:void addCount() {m_count++;}int32_t getCount() {return m_count;}private:static Singleton* instance; //静态指针变量Singleton(){} //私有化类的构造函数int32_t m_count{0};
};Singleton* Singleton::instance = nullptr; //静态成员类外初始化int main(int argc, char* argv[])
{Singleton* single_0 = Singleton::getSingletonInstance();single_0->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;Singleton* single_1 = Singleton::getSingletonInstance();single_1->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl; return 0;
}
输出
single_0 value is: 1single_0 value is: 2
single_1 value is: 2
2.2 线程安全
2.1中的示例是线程不安全的,假如有多个线程同时调用getSingletonInstance(),此时检测到instance是nullptr,就会导致单例的崩溃,造成内存泄漏;
通过加锁来实现
示例
/** @brief : design patterns singleton* @author : your name* @compile : g++ -g singleton_main.cc -o d -std=c++11* @date : 2023/04/18* @lastEditorDate: */#include <iostream>
#include <string>
#include <mutex>//懒汉模式
std::mutex mtx; //全局的锁
class Singleton
{
public:static Singleton* getSingletonInstance() //访问函数{if(instance == nullptr){std::lock_guard<std::mutex> guard(mtx); if(instance == nullptr){instance = new Singleton;} }return instance;}public:void addCount() {m_count++;}int32_t getCount() {return m_count;}private: static Singleton* instance; //静态指针变量Singleton(){} //私有化类的构造函数int32_t m_count{0};
};
Singleton* Singleton::instance = nullptr; //静态成员类外初始化int main(int argc, char* argv[])
{Singleton* single_0 = Singleton::getSingletonInstance();single_0->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;Singleton* single_1 = Singleton::getSingletonInstance();single_1->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl; return 0;
}
输出
single_0 value is: 1single_0 value is: 2
single_1 value is: 2
使用 c++11 中局部静态变量是线程安全的性质
示例
/** @brief : design patterns singleton* @author : your name* @compile : g++ -g singleton_main.cc -o d -std=c++11* @date : 2023/04/18* @lastEditorDate: */#include <iostream>
#include <string>
#include <mutex>//懒汉模式
class Singleton
{
public:static Singleton* getSingletonInstance() //访问函数{static Singleton instance; //静态指针变量return &instance;}public:void addCount() {m_count++;}int32_t getCount() {return m_count;}private: Singleton(){} //私有化类的构造函数int32_t m_count{0};
};int main(int argc, char* argv[])
{Singleton* single_0 = Singleton::getSingletonInstance();single_0->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;Singleton* single_1 = Singleton::getSingletonInstance();single_1->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl; return 0;
}
输出
single_0 value is: 1single_0 value is: 2
single_1 value is: 2
3. 饿汉模式
指单例实例在程序运行时被立即执行初始化
示例
/** @brief : design patterns singleton* @author : your name* @compile : g++ -g singleton_main.cc -o d -std=c++11* @date : 2023/04/18* @lastEditorDate: */#include <iostream>
#include <string>
#include <mutex>//饿汉模式
class Singleton
{
public:static Singleton* getSingletonInstance() //访问函数{ return instance;}public:void addCount() {m_count++;}int32_t getCount() {return m_count;}private:static Singleton* instance; //静态指针变量Singleton(){} //私有化类的构造函数int32_t m_count{0};
};Singleton* Singleton::instance = new Singleton; //静态成员类外初始化int main(int argc, char* argv[])
{Singleton* single_0 = Singleton::getSingletonInstance();single_0->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;Singleton* single_1 = Singleton::getSingletonInstance();single_1->addCount();std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl; return 0;
}
输出
single_0 value is: 1single_0 value is: 2
single_1 value is: 2
4. 在开发过程中的使用
在项目的使用过程中,可以将单例设计成为类模板;这样其它类在设计的时候不用考虑,是否需要将其设计成为单例;
其它类如果需要单例属性,只需要通过单例模板对其进行赋能即可;
示例
/** @brief : design patterns singleton* @author : your name* @compile : g++ -g singleton_main.cc -o d -std=c++11* @date : 2023/04/18* @lastEditorDate: */#include <iostream>
#include <string>
#include <mutex>template<class T>
class Singleton
{
public:static T* getSingletonInstance() //访问函数{static T instance; //静态指针变量return &instance;}
private: Singleton(){} //私有化类的构造函数
};class C1
{
public:void addCount() {m_count++;}int32_t getCount() {return m_count;} private: int32_t m_count{0};
};int main(int argc, char* argv[])
{auto re1 = Singleton<C1>::getSingletonInstance();re1->addCount();std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;auto re2 = Singleton<C1>::getSingletonInstance();re2->addCount();std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;std::cout<<"re2->getCount() value is: "<<re2->getCount()<<std::endl;return 0;
}
输出
re1->getCount() value is: 1
re1->getCount() value is: 2
re2->getCount() value is: 2
相关文章:
创建型模式——单例(singleton)
1. 模式说明 单例模式保证类只有一个实例;创建一个对象,当你创建第二个对象的时候,此时你获取到的是已经创建过的对象,而不是一个新的对象; 1.1 使用场景 共享资源的访问权限;任务的管理类;数…...

算法:迷宫问题
描述 定义一个二维数组 N*M ,如 5 5 数组下所示: int maze[5][5] { 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或…...

聊聊并发编程的12种业务场景
前言 并发编程是一项非常重要的技术,无论在面试,还是工作中出现的频率非常高。 并发编程说白了就是多线程编程,但多线程一定比单线程效率更高? 答:不一定,要看具体业务场景。 毕竟如果使用了多线程&…...

MySQL执行顺序
MySQL执行顺序 MySQL语句的执行顺序也是在面试过程中经常问到的问题,并且熟悉执行顺序也有助于SQL语句的编写。 SELECT FROM JOIN ON WHERE GROUP BY HAVING ORDER BY LIMIT执行顺序如下: FROM ON JOIN WHERE GROUP BY # (开始使用别名) SUM # SUM等…...

引领真无线耳机未来趋势,NANK南卡OE骨传导真无线耳机惊艳亮相
传统的蓝牙耳机存在很多问题,例如续航时间短、长期佩戴耳朵会不舒服,甚至影响听力等等。为了解决这些问题,在骨传导领域深耕十多年的南卡品牌推出了这款真无线骨传导耳机——NANK南卡 OE。 NANK南卡OE即将正式上线,这一消息一经宣…...

5款写作神器,帮助你写出5w+爆款文案,好用到哭
我不允许还有文案小白、新手博主不知道这5款写作利器! 每次一写文案就头秃的新媒体工作者,赶紧看过来吧!这5款好用到爆的写作神器,喝一杯咖啡的时间就能完成写作。 我和同事都是用它们,出了很多的爆款,现…...

相交链表问题
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后&…...
[ubuntu] ax200网卡虚接,导致系统根目录占满而无法进入系统的奇葩问题
20230508,我像往常一样,打开电脑发现根目录满了,报警了,所以按照网上的教程,清理了一下根目录的文件,没想到背后是网卡问题… 文章目录 1.进入终端模式2.查看占用情况3.清理系统log文件3.1 清理/var/log/syslog3.2 清…...
本地字体库的引入方法
本地字体库是指在计算机系统中存储的一组字体文件,通常包含多种字体格式,如TTF、OTF、WOFF等。引入本地字体库可以让用户在使用计算机时可以选择不同的字体,从而提高用户的使用体验。 本地字体库的引入方式有多种,其中比较常用的是…...

7种优秀的导航菜单设计总结
导航是应用程序界面中最常见的模块之一,在链接应用程序中起着每个页面的作用。 不同的设计需求和业务目标决定了导航的设计因品而异,移动设备的尺寸远小于计算机。因此,在设计移动终端导航时,应考虑更全面,以确保简单…...
Problem E. 矩阵游戏 (2023年ccpc河南省赛)
原题链接: https://codeforces.com/gym/104354 题意: 有一个n*m的矩阵,只有三种字符:0,1和?。从[1,1]走到[n,m],每次只能向下走或者向下走。当走到1的时候得一分,走到0的时候不得分,走到?的时候可以将他…...

数字孪生模型构建理论及应用
源自:计算机集成制造系统 作者:陶飞 张贺 戚庆林 徐 俊 孙铮 胡天亮 刘晓军 刘庭煜 关俊涛 陈畅宇 孟凡伟 张辰源 李志远 魏永利 朱铭浩 肖斌 摘 要 数字孪生作为实现数字化转型和促进智能化升级的重要使能途径,一直备受各…...
Vue面试题:30道含答案和代码示例的练习题
Vue中的双向数据绑定是怎么实现的? 双向数据绑定通过使用v-model指令实现。v-model指令会在表单元素上创建一个监听器,在用户输入时实时更新Vue实例的数据,并且在Vue实例数据变化时更新表单元素的值。 如何在Vue中定义一个方法?…...
2023-05-09 LeetCode每日一题(有效时间的数目)
2023-05-09每日一题 一、题目编号 2437. 有效时间的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 5 的字符串 time ,表示一个电子时钟当前的时间,格式为 “hh:mm” 。最早 可能的时间是 “00:00” ,最晚 可能的时间…...

第三节课 Linux文件权限
目录 文件属性详解 权限修改 文件所有者与属组修改 文件默认权限修改 Linux是多人多任务的操作系统,因此可能常常会有多人使用一台机器, 为了考虑每个人的隐私、方便用户合作,每个文件都有三类用户,权限是基于这三类用户设定的…...
开发STC89C51系列单片机需要的单片机技术
端口操作:控制单片机的输入输出端口,与外界进行通信。中断优先级:当多个中断同时发生时,确定哪个中断优先级更高,优先响应。时钟模块:控制单片机的时钟,可以精确计时。PWM技术:实现模…...
分布式键值存储是什么?(分布式键值存储大值)
文章目录 什么是分布式键值存储?分布式键值存储“大值”指什么? 什么是分布式键值存储? 分布式键值存储是一种分布式数据存储系统,它将数据存储为键值对的形式,并将这些键值对分散在多个节点上。每个节点都可以独立地…...

多线程(线程同步和互斥+线程安全+条件变量)
线程互斥 线程互斥: 任何时刻,保证只有一个执行流进入临界区访问临界资源,通常对临界资源起到保护作用 相关概念 临界资源: 一次仅允许一个进程使用的共享资源临界区: 每个线程内部,访问临界资源的代码&am…...
Flutter学习——开发Flutter需要的技能
第二章 Flutter开发所需要掌握的知识 文章目录 第二章 Flutter开发所需要掌握的知识前言一、开发语言Dart语言Android/Ios知识 二、组件学习三、调试与性能优化总结 前言 上一章,介绍了Flutter的来源和平台支持及特点,这一章,来梳理一下学习…...

SPSS如何进行因子分析和主成分分析之案例实训?
文章目录 0.引言1.因子分析2.主成分分析 0.引言 因科研等多场景需要进行数据统计分析,笔者对SPSS进行了学习,本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结,本文对因子分析和主成分分析进行阐述。 1.因…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...