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

目录

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

橙色
详细可参考该篇文章: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;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RH850P1X芯片学习笔记-Pin Functions

文章目录 Pin Connection Diagrams术语定义 Pin ListPort OverviewIntroductionFunctional OverviewPort CategoryOperation Mode运行模式 Port Function寄存器地址映射 Port寄存器描述Pn/JP0 — Port RegisterPPRn/JPPR0 — Port Pin Read RegisterPMn/JPM0 — Port Mode Regi…

采集伪原创洗稿,实现文章创作的方法

各位写手小伙伴们&#xff0c;今天要和大家分享一些关于伪原创的方法和经验&#xff0c;希望这些建议能够在你们的写作之旅中派上用场。 首先我们需要明确一下&#xff0c;伪原创并不是鼓励抄袭&#xff0c;而是一种在保留原文核心思想的同时&#xff0c;通过巧妙的方式改写&a…

2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A

2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A 目录 2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-A 需要环境或者解析可以私信 &#xff08;二&#xff09;A 模块基础设施设置/安全加固&#xff08;200 分&…

Footprint Analytics x Future3 万字研报:AI 与 Web3 数据行业融合的现状、竞争格局与未来机遇探析(上)

GPT的横空出世将全球的目光吸引至大语言模型&#xff0c;各行各业都尝试着利用这个“黑科技”提高工作效率&#xff0c;加速行业发展。Future3 Campus携手Footprint Analytics共同深入研究AI与Web3结合的无限可能&#xff0c;联合发布了《AI与Web3数据行业融合现状、竞争格局与…

操作系统原理-作业二-进程调度与死锁

1.设某系统中有四个进程 P1 、 P2 、 P3 和 P4 &#xff0c;它们的到达时刻依次为 0ms 、 1ms 、 2ms 、 3ms &#xff0c;估计运行时间分别为 6ms 、 1ms 、 8ms 、 4ms &#xff0c;若系统采用基于时间片轮转的三 级反馈队列调度算法进行调度&#xff0c;其中第一级队…

深度解析大模型背后的知识储存与提取:背诵不等于理解/MongoDB发布生成式AI新功能,大幅提高开发者工作效率和体验|魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件&#x1f525;&#xff0c;更新AIGC的最新动态&#xff0c;生成相应的魔法简报&#xff0c;节省阅读时间&#x1f47b; &#x1f525;资讯预览 Mistral AI发布开源语言模型Mistral 7B&#xff0c;性能超越规模更大的Llama…

机器学习实验四:贝叶斯分类器

系列文章目录 机器学习实验一&#xff1a;线性回归机器学习实验二&#xff1a;决策树模型机器学习实验三&#xff1a;支持向量机模型机器学习实验四&#xff1a;贝叶斯分类器机器学习实验五&#xff1a;集成学习机器学习实验六&#xff1a;聚类 文章目录 系列文章目录一、实验…

计算机网络之IP篇

目录 一、IP 的基本认识 二、DNS 三、ARP 四、DHCP 五、NAT 六、ICMP 七、IGMP 七、ping 的工作原理 ping-----查询报文的使用 traceroute —— 差错报文类型的使用 八、断网了还能 ping 通 127.0.0.1 吗&#xff1f; 8.1、什么是 127.0.0.1 &#xff1f; 8.2、为…

11.10Redis基础

一.安装,启动,操作 二.远程连接 三.官方文档 https://redis.io/commands/ 四.Redis的数据类型 1.String 2.Hash(注意: value是字典类型) 3.List(类似于队列) 4.Set(无序) 5. ZSet(有序) 五.持久化 六.分布 七.SpringBoot集成Redis 1.添加依赖 2. 配置Redis 3.操作Redis(Serv…

如何选择适合自己的成品短视频app源码?

在当今数字化社会&#xff0c;短视频成为了人们日常生活中不可或缺的一部分。对于想要投身这一领域的创业者来说&#xff0c;选择适合自己的成品短视频app源码显得至关重要。在这篇文章中&#xff0c;我将为您提供一些建议&#xff0c;帮助您在众多选择中找到最合适的短视频app…

红警For Mac(RAM芯片可玩)

1、文件损坏解决版本&#xff01; 执行以下命令&#xff0c;&#xff08;注意&#xff1a;命令2应用路径根据实际情况修改&#xff09; sudo spctl --master-disable sudo xattr -r -d com.apple.quarantine /Applications/红警2尤里复仇M芯片.app2、新系统14&#xff0c;第一…

【3】密评-物理和环境安全测评

0x01 依据 GB/T 39786 -2021《信息安全技术 信息系统密码应用基本要求》针对等保三级系统要求&#xff1a; 物理和环境层面&#xff1a; a&#xff09;宜采用密码技术进行物理访问身份鉴别,保证重要区域进入人员身份的真实性&#xff1b; b&#xff09;宜采用密码技术保证电子门…

Centos7.4安装nginx1.24.0_安装详细步骤---Linux工作笔记066

以前安装的太模糊了,干脆重新写一个: 1.首先下载对应的nginx-1.24.0.tar.gz安装文件 2.然后: 去执行命令 安装依赖 yum install -y gcc yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install -y openssl openssl-devel 3.然后:去解压 tar -zxvf ngi…

mac苹果笔记本电脑如何强力删除卸载app软件?

苹果电脑怎样删除app&#xff1f;不是把app移到废纸篓就行了吗&#xff0c;十分简单呢&#xff01; 其实不然&#xff0c;因为在Mac电脑上&#xff0c;删除应用程序只是删除了应用程序的主要组件。大多数时候&#xff0c;系统会有一个相当长的目录&#xff0c;包含所有与应用程…

08、分析测试执行时间及获取pytest帮助

官方用例 # content of test_slow_func.py import pytest from time import sleeppytest.mark.parametrize(delay,(1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.0,0.1,0.2,0,3)) def test_slow_func(delay):print("test_slow_func {}".format(delay))sleep(delay)assert…

分享68个节日PPT,总有一款适合您

分享68个节日PPT&#xff0c;总有一款适合您 68个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1c1-K7Gjw8bWT-cbToIZQTA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

vue3 setup语法糖 多条件搜索(带时间范围)

目录 前言&#xff1a; setup介绍&#xff1a; setup用法&#xff1a; 介绍&#xff1a; 前言&#xff1a; 不管哪个后台管理中都会用到对条件搜索带有时间范围的也不少见接下来就跟着我步入vue的多条件搜索&#xff08;带时间范围&#xff09; 在 Vue 3 中&#xff0c;你…

YOLOv8改进 | 2023 | Deformable-LKA可变形大核注意力(涨点幅度超高)

一、本文介绍 本文给大家带来的改进内容是Deformable-LKA&#xff08;可变形大核注意力&#xff09;。Deformable-LKA结合了大卷积核的广阔感受野和可变形卷积的灵活性&#xff0c;有效地处理复杂的视觉信息。这一机制通过动态调整卷积核的形状和大小来适应不同的图像特征&…

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

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

vmware虚拟机磁盘扩容与挂载

解决工作中遇到vmware虚拟机磁盘容量不足的问题 一、添加新磁盘并将磁盘挂载到空目录 1、关机加硬盘 1&#xff09;首先&#xff0c;需要将虚拟机关机&#xff0c;然后在虚拟机设置页面进行硬盘添加 2) 默认选择SCSI&#xff0c;点击下一步 3) 保持默认&#xff0c;点击下一步…