【设计模式】单例模式代码设计

目录

  • 单例模式简介
  • 饿汉单例模式
  • 懒汉单例模式
  • 线程安全的懒汉单例模式

橙色
详细可参考该篇文章:C++设计模式 - 单例模式

单例模式简介

单例模式指的是,无论怎么获取,永远只能得到该类类型的唯一一个实例对象,那么设计一个单例就必须要满足下面三个条件:

1、构造函数私有化,这样用户就不能任意定义该类型的对象了
2、定义该类型唯一的对象
3、通过一个static静态成员方法返回唯一的对象实例

饿汉单例模式

饿汉式单例模式,顾名思义,就是程序启动时就实例化了该对象,并没有推迟到第一次使用该对象时再进行实例化

为什么getInstance成员函数要加static关键字?因为普通成员方法的调用还是要依赖于对象,但现在没对象,现在是通过接口来获取对象的,所以 返回唯一的对象实例的函数 应该是静态成员函数。

下面这个是饿汉式单例模式:

#include <iostream>
using namespace std;
/*
单例模式:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*///饿汉式单例模式,一定是线程安全的
class Singleton
{
public:static Singleton* getInstance()//#3 获取类的唯一实例对象的接口方法{return &instance;}
private:static Singleton instance;//#2 定义一个唯一类的实例对象Singleton()     //#1 构造函数私有化{}Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton&) = delete;
};Singleton Singleton::instance;int main()
{Singleton *p1 = Singleton::getInstance();Singleton *p2 = Singleton::getInstance();Singleton *p3 = Singleton::getInstance();cout << p1 << " " << p2 << " " << p3 << endl;return 0;
}

在这里插入图片描述

但有时呢,可能你整个任务过程中都没有试图获取过该单例对象,但函数是先于程序执行载入的,那么可能饿汉模式,先定义了一个唯一的实例对象,并且构造函数进行了大量的初始化,所以在程序启动时就会先创建出一个实例化对象,白白浪费很多时间。所以有时就会用懒汉模式

懒汉单例模式

下面这个是懒汉式单例模式,把对象的实例化延迟到第一次获取该实例对象时。在程序启动时,它仅仅先创建了一个指针而不是一个对象

可重入函数:在多线程中能够被不同线程重复调用,即一个线程调用还没结束时,另一个线程又来调用,这样的函数就称为可重入函数

#include <iostream>
using namespace std;/*
单例模式:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*///懒汉式单例模式,存在线程安全的问题
class Singleton
{
public:static Singleton* getInstance()//#3 获取类的唯一实例对象的接口方法{if(instance==nullptr){instance = new Singleton();}return instance;}
private:static Singleton *instance;//#2 定义一个唯一类的实例对象Singleton()     //#1 构造函数私有化{}Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton&) = delete;
};Singleton* Singleton::instance=nullptr;int main()
{Singleton *p1 = Singleton::getInstance();Singleton *p2 = Singleton::getInstance();Singleton *p3 = Singleton::getInstance();cout << p1 << " " << p2 << " " << p3 << endl;return 0;
}

在这里插入图片描述

线程安全的懒汉单例模式

饿汉单例模式中,单例对象定义成了一个static静态对象,它是在程序启动时,main函数运行之前就初始化好的,因此不存在线程安全问题,可以放心的在多线程环境中使用。但上面的懒汉模式代码却不是安全的

在静态成员变量instance的前面加volatile关键字,是因为在多线程中cpu为了加快速度,往往会将静态成员变量的值都拷贝一份,带到各个的线程中去,放到cpu的缓存里。而加了volatile,加了该关键字后,就禁止了各个线程拷贝该变量。如果该静态成员变量的值发生改变,那么所有的线程都会立刻看到静态成员变量的改变

下面是线程安全的懒汉单例模式:

#include <iostream>
#include<mutex>
using namespace std;/*
单例模式:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*/mutex mtx;
//懒汉式单例模式=》是不是线程安全的呢?=》线程安全的懒汉式单例模式    
class Singleton
{
public://是不是可重入函数呢?  锁+双重判断static Singleton* getInstance()//#3 获取类的唯一实例对象的接口方法{//lock_guard<mutex> guard(mtx);//在这里加锁锁的粒度太大了,如果是单线程的话,调用该函数还是要每次加锁解锁if(instance==nullptr){lock_guard<mutex> guard(mtx);if(instance==nullptr){/*开辟函数构造函数私有化给instance赋值*/instance = new Singleton();}   }return instance;}
private:static Singleton *volatile instance;//#2 定义一个唯一类的实例对象Singleton()     //#1 构造函数私有化{}Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton&) = delete;
};Singleton*volatile Singleton::instance=nullptr;int main()
{Singleton *p1 = Singleton::getInstance();Singleton *p2 = Singleton::getInstance();Singleton *p3 = Singleton::getInstance();cout << p1 << " " << p2 << " " << p3 << endl;return 0;
}

在这里插入图片描述

当然,线程安全的懒汉模式还有另一种写法,如下:

#include <iostream>
#include<mutex>
using namespace std;/*
单例模式:
饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了
懒汉式单例模式:唯一的实例对象,直到第一次获取它的时候,才产生
*///懒汉式单例模式
class Singleton
{
public://仅在第一次调用该函数的时候,才会创建该对象static Singleton* getInstance()//#3 获取类的唯一实例对象的接口方法{//函数静态局部变量的初始化,在汇编指令上已经自动添加了线程互斥指令了static Singleton instance;return &instance;}
private:Singleton()     //#1 构造函数私有化{}Singleton(const Singleton &) = delete;Singleton &operator=(const Singleton&) = delete;
};int main()
{Singleton *p1 = Singleton::getInstance();Singleton *p2 = Singleton::getInstance();Singleton *p3 = Singleton::getInstance();cout << p1 << " " << p2 << " " << p3 << endl;return 0;
}

在这里插入图片描述

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

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

相关文章

聊聊部署在不同K8S集群上的服务如何利用nginx-ingress进行灰度发布

前言 之前有篇文章聊聊如何利用springcloud gateway实现简易版灰度路由,里面的主人公又有一个需求&#xff0c;他们有个服务是没经过网关的&#xff0c;而是直接通过nginx-ingress暴露出去&#xff0c;现在这个服务也想做灰度&#xff0c;他知道在同个集群如何利用nginx-ingre…

Git 分支合并时 Merge, Rebase, Squash 的使用场景

前言 Git 的分支设计大大提升了并行开发的能力&#xff0c;但相应的&#xff0c;也就要解决如何进行分支合并。毕竟分久必合&#xff0c;最终还是要把大家的工作合并起来&#xff0c;进行统一发布的。在合并时&#xff0c;通常有三种操作&#xff1a; Merge commitsRebaseSqu…

Vue学习计划--Vue2(二)Vue代理方式

Vue data中的两种方式 对象式 data:{}函数式 data(){return {} }示例&#xff1a; <body><div id"app">{{ name }} {{ age}} {{$options}}<input type"text" v-model"value"></div><script>let vm new Vue({el: …

Linux操作系统之wget下载软件并安装

文章目录 前言一、apt下载二、wget下载1、新建目录存放文件2、根据下载地址使用wget下载安装包3、解压包4、命令指定目录&#xff0c;让其生效如有启发&#xff0c;可点赞收藏哟~ 前言 一般安装可以直接使用apt命令&#xff0c;不过安转的不是最新版本的&#xff0c;且没法指定…

驱动开发--内核添加新功能

Ubuntu下这个文件为开发板ls命令的结果 内核的内容&#xff1a; mm&#xff1a;内存管理 fs&#xff1a;文件系统 net&#xff1a;网络协议栈 drivers&#xff1a;驱动设备 arch与init&#xff1a;跟启动相关 kernel与ipc&#xff1a;任务&#xff0c;进程相关 向内核增…

Depop自养号下单教程,测评环境、IP与买家资料的关键

Depop是一家总部位于英国伦敦的在线时尚市场和社交媒体平台。该平台于2011年由Simon Beckerman创立&#xff0c;旨在提供一个结合了时尚、创意和社交互动元素的独特购物体验。Depop已经发展成为一个备受欢迎的时尚社交应用&#xff0c;吸引了全球范围内的卖家和购物者。提供了一…

一文读懂3D开发工具HOOPS SDK

前言 Tech Soft 3D是全球领先的3D领域开发工具提供商&#xff0c;可帮助软件团队交付成功的应用程序。Tech Soft 3D成立于1996年&#xff0c;该公司的工具包产品为全球数亿台计算机上运行的近500个独特应用程序提供支持&#xff0c;已经助力SolidWorks、AutoDesk、GrabCAD、CD…

kafka 3.x 学习笔记

kafka 3.x 学习笔记 在 kafka 2.8.0 版本之前&#xff0c;安装使用 kafka 需要配套安装 zookeeper&#xff0c;但在 2.8.0 版本之后&#xff0c;不再需要安装 zookeeper&#xff0c;本次学习笔记采用的 kafka 版本为 3.0.0。 文章目录 kafka 3.x 学习笔记一、kafka 定义1 什么是…

任务管理器快捷键分享!这些知识很有用!

“我刚学习使用电脑没多久&#xff0c;想问问大家任务管理器这个功能有什么用处呀&#xff1f;在使用任务管理器时有什么快捷键能快速进入吗&#xff1f;感谢解答&#xff01;” 在日常使用电脑的过程中&#xff0c;我们经常需要打开任务管理器来进行一些操作。而掌握任务管理器…

大数据SpringBoot项目|基于SpringBoot+MyBatis框架健身房管理系统的设计与实现

大数据SpringBoot项目|基于SpringBootMyBatis框架健身房管理系统的设计与实现 摘 要:本文基于Spring Boot和MyBatis框架&#xff0c;设计并实现了一款综合功能强大的健身房管理系统。该系统涵盖了会员卡查询、会员管理、员工管理、器材管理以及课程管理等核心功能&#xff0c;…

机器视觉中的图像增强与对比度调整技术

在机器视觉中&#xff0c;图像增强与对比度调整技术是常用的方法&#xff0c;旨在改善图像的质量和视觉效果&#xff0c;或将图像转换成更适合人眼观察或机器分析识别的形式。 图像增强技术可以针对给定图像的应用场合&#xff0c;有目的地强调图像的整体或局部特性&#xff0…

移动端APP自动化测试框架-UiAutomator2基础

很早以前&#xff0c;我用uiautomatorjava实践过Android APP自动化测试&#xff0c;不过今天要提的不是uiautomator&#xff0c;而是uiautomator2。听起来uiautomator2像是uiautomator的升级版&#xff0c;但是这两款框架仅仅是名字上比较相似&#xff0c;实际上没有任何关联。…

硬盘分区丢失?这样轻松恢复!

​“在我安装操作系统的过程中&#xff0c;我先把C盘&#xff08;100G&#xff09;进行了格式化&#xff0c;而我的D盘大小为297G&#xff0c;然而在Win PE中&#xff0c;所显示的仅是247G&#xff08;CD盘总容量&#xff09;&#xff0c;这247G是空无一物的。让我感到困惑的是…

02、pytest环境准备

工具准备 python官网下载&#xff1a;https://www.python.org/pycharm官网下载&#xff1a;https://www.jetbrains.com.cn/en-us/pycharm/pytest官方文档&#xff1a;https://docs.pytest.org/en/7.4.x/python-office官网文档&#xff1a;http://www.python-office.com/ 参考…

《消息队列MyMQ》——参考RabbitMQ实现

目录 一、什么是消息队列&#xff1f; 二、需求分析 1&#xff09;核心概念 2&#xff09;核心API 3&#xff09;交换机类型 4&#xff09;持久化 5&#xff09;网络通信 ​编辑 6&#xff09;消息应答 三、 模块划分 四、创建核心类 1.ExChange 2.MSGQueue 3.Bind…

NSSCTF 文件上传漏洞题目

目录 [SWPUCTF 2021 新生赛]easyupload1.0 [SWPUCTF 2021 新生赛]easyupload2.0 [SWPUCTF 2021 新生赛]easyupload3.0 [SWPUCTF 2021 新生赛]easyupload1.0 这是一个文件上传漏洞的题目 我们的思路是上传一句话木马&#xff0c;用工具进行连接 先编写一句话木马 将文件后缀…

【深度学习】Stable Diffusion中的Hires. fix是什么?Hires. fix原理

文章目录 **Hires. fix****Extra noise**Upscalers Hires. fix https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#hires-fix 提供了一个方便的选项&#xff0c;可以部分地以较低分辨率呈现图像&#xff0c;然后将其放大&#xff0c;最后在高分辨率下添…

【数电笔记】16-卡诺图绘制(逻辑函数的卡诺图化简)

目录 说明&#xff1a; 最小项卡诺图的组成 1. 相邻最小项 2. 卡诺图的组成 2.1 二变量卡诺图 2.2 三表变量卡诺图 2.3 四变量卡诺图 3. 卡诺图中的相邻项&#xff08;几何相邻&#xff09; 说明&#xff1a; 笔记配套视频来源&#xff1a;B站&#xff1b;本系列笔记并…

文献速递:(第三部分)— (超声非破坏性评估中合成和增强训练数据生成与评估的最新研究进展)

文献速递&#xff1a;&#xff08;第三部分&#xff09;— &#xff08;超声非破坏性评估中合成和增强训练数据生成与评估的最新研究进展&#xff09; Title 题目 A review of synthetic and augmented training data for machine learning in ultrasonic non-destructive e…

iOS17桌面待办事项提醒小组件,让的iPhone变身提醒神器

在现代社会&#xff0c;每天都有太多的事情需要处理&#xff0c;而我经常发现自己在繁忙中遗漏一些重要的事项。曾经&#xff0c;我每次都要在纸上记下要做的事情&#xff0c;可事后发现&#xff0c;这也没能解决我的忘性问题。 直到我尝试了一个新的方式&#xff0c;我的iPho…