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

创建型模式——单例(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. 模式说明 单例模式保证类只有一个实例&#xff1b;创建一个对象&#xff0c;当你创建第二个对象的时候&#xff0c;此时你获取到的是已经创建过的对象&#xff0c;而不是一个新的对象&#xff1b; 1.1 使用场景 共享资源的访问权限&#xff1b;任务的管理类&#xff1b;数…...

算法:迷宫问题

描述 定义一个二维数组 N*M &#xff0c;如 5 5 数组下所示&#xff1a; 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, }; 它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&#xff0c;只能横着走或…...

聊聊并发编程的12种业务场景

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

MySQL执行顺序

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

引领真无线耳机未来趋势,NANK南卡OE骨传导真无线耳机惊艳亮相

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

5款写作神器,帮助你写出5w+爆款文案,好用到哭

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

相交链表问题

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&…...

[ubuntu] ax200网卡虚接,导致系统根目录占满而无法进入系统的奇葩问题

20230508&#xff0c;我像往常一样,打开电脑发现根目录满了&#xff0c;报警了&#xff0c;所以按照网上的教程&#xff0c;清理了一下根目录的文件&#xff0c;没想到背后是网卡问题… 文章目录 1.进入终端模式2.查看占用情况3.清理系统log文件3.1 清理/var/log/syslog3.2 清…...

本地字体库的引入方法

本地字体库是指在计算机系统中存储的一组字体文件&#xff0c;通常包含多种字体格式&#xff0c;如TTF、OTF、WOFF等。引入本地字体库可以让用户在使用计算机时可以选择不同的字体&#xff0c;从而提高用户的使用体验。 本地字体库的引入方式有多种&#xff0c;其中比较常用的是…...

7种优秀的导航菜单设计总结

导航是应用程序界面中最常见的模块之一&#xff0c;在链接应用程序中起着每个页面的作用。 不同的设计需求和业务目标决定了导航的设计因品而异&#xff0c;移动设备的尺寸远小于计算机。因此&#xff0c;在设计移动终端导航时&#xff0c;应考虑更全面&#xff0c;以确保简单…...

Problem E. 矩阵游戏 (2023年ccpc河南省赛)

原题链接&#xff1a; https://codeforces.com/gym/104354 题意&#xff1a; 有一个n*m的矩阵&#xff0c;只有三种字符&#xff1a;0,1和?。从[1,1]走到[n,m],每次只能向下走或者向下走。当走到1的时候得一分&#xff0c;走到0的时候不得分&#xff0c;走到?的时候可以将他…...

数字孪生模型构建理论及应用

源自&#xff1a;计算机集成制造系统 作者&#xff1a;陶飞 张贺 戚庆林 徐 俊 孙铮 胡天亮 刘晓军 刘庭煜 关俊涛 陈畅宇 孟凡伟 张辰源 李志远 魏永利 朱铭浩 肖斌 摘 要 数字孪生作为实现数字化转型和促进智能化升级的重要使能途径&#xff0c;一直备受各…...

Vue面试题:30道含答案和代码示例的练习题

Vue中的双向数据绑定是怎么实现的&#xff1f; 双向数据绑定通过使用v-model指令实现。v-model指令会在表单元素上创建一个监听器&#xff0c;在用户输入时实时更新Vue实例的数据&#xff0c;并且在Vue实例数据变化时更新表单元素的值。 如何在Vue中定义一个方法&#xff1f;…...

2023-05-09 LeetCode每日一题(有效时间的数目)

2023-05-09每日一题 一、题目编号 2437. 有效时间的数目二、题目链接 点击跳转到题目位置 三、题目描述 给你一个长度为 5 的字符串 time &#xff0c;表示一个电子时钟当前的时间&#xff0c;格式为 “hh:mm” 。最早 可能的时间是 “00:00” &#xff0c;最晚 可能的时间…...

第三节课 Linux文件权限

目录 文件属性详解 权限修改 文件所有者与属组修改 文件默认权限修改 Linux是多人多任务的操作系统&#xff0c;因此可能常常会有多人使用一台机器&#xff0c; 为了考虑每个人的隐私、方便用户合作&#xff0c;每个文件都有三类用户&#xff0c;权限是基于这三类用户设定的…...

开发STC89C51系列单片机需要的单片机技术

端口操作&#xff1a;控制单片机的输入输出端口&#xff0c;与外界进行通信。中断优先级&#xff1a;当多个中断同时发生时&#xff0c;确定哪个中断优先级更高&#xff0c;优先响应。时钟模块&#xff1a;控制单片机的时钟&#xff0c;可以精确计时。PWM技术&#xff1a;实现模…...

分布式键值存储是什么?(分布式键值存储大值)

文章目录 什么是分布式键值存储&#xff1f;分布式键值存储“大值”指什么&#xff1f; 什么是分布式键值存储&#xff1f; 分布式键值存储是一种分布式数据存储系统&#xff0c;它将数据存储为键值对的形式&#xff0c;并将这些键值对分散在多个节点上。每个节点都可以独立地…...

多线程(线程同步和互斥+线程安全+条件变量)

线程互斥 线程互斥&#xff1a; 任何时刻&#xff0c;保证只有一个执行流进入临界区访问临界资源&#xff0c;通常对临界资源起到保护作用 相关概念 临界资源&#xff1a; 一次仅允许一个进程使用的共享资源临界区&#xff1a; 每个线程内部&#xff0c;访问临界资源的代码&am…...

Flutter学习——开发Flutter需要的技能

第二章 Flutter开发所需要掌握的知识 文章目录 第二章 Flutter开发所需要掌握的知识前言一、开发语言Dart语言Android/Ios知识 二、组件学习三、调试与性能优化总结 前言 上一章&#xff0c;介绍了Flutter的来源和平台支持及特点&#xff0c;这一章&#xff0c;来梳理一下学习…...

SPSS如何进行因子分析和主成分分析之案例实训?

文章目录 0.引言1.因子分析2.主成分分析 0.引言 因科研等多场景需要进行数据统计分析&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对因子分析和主成分分析进行阐述。 1.因…...

Dreamweaver CS6 表单实战:从零构建交互式网页数据收集器

1. 为什么表单是网页设计的必备技能 表单就像网站和用户之间的对话窗口。想象一下&#xff0c;当你想参加一个线下活动时&#xff0c;主办方通常会让你填写一张纸质报名表——姓名、联系方式、参加人数等信息。网页表单就是这种纸质表格的电子版&#xff0c;但功能要强大得多。…...

AI模型版本管理失控真相(2026奇点大会闭门报告首曝:92%团队仍在用传统Git硬扛LLM微调)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生版本控制&#xff1a;2026奇点智能技术大会Git for AI最佳实践 在2026奇点智能技术大会上&#xff0c;Git for AI正式成为AI工程化基础设施的核心组件。与传统Git不同&#xff0c;AI原生版本控制…...

免费解锁B站4K大会员视频下载:三步完成离线观看的终极指南

免费解锁B站4K大会员视频下载&#xff1a;三步完成离线观看的终极指南 【免费下载链接】bilibili-downloader B站视频下载&#xff0c;支持下载大会员清晰度4K&#xff0c;持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为B站大会员…...

3个步骤如何为Unity应用集成Perseus原生库功能扩展

3个步骤如何为Unity应用集成Perseus原生库功能扩展 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus Perseus是一个专为Unity Android应用设计的原生库补丁框架&#xff0c;通过无偏移地址设计实现功能扩展…...

抖音视频下载终极指南:douyin-downloader帮你轻松保存无水印高清内容

抖音视频下载终极指南&#xff1a;douyin-downloader帮你轻松保存无水印高清内容 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser …...

实战指南:轻松掌握ModTheSpire模组加载器的完整使用方法

实战指南&#xff1a;轻松掌握ModTheSpire模组加载器的完整使用方法 【免费下载链接】ModTheSpire External mod loader for Slay The Spire 项目地址: https://gitcode.com/gh_mirrors/mo/ModTheSpire ModTheSpire是一款专为《杀戮尖塔》设计的强大模组加载器&#xff…...

开发AI应用时如何借助Taotoken实现模型故障的自动容灾

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 开发AI应用时如何借助Taotoken实现模型故障的自动容灾 在构建依赖大模型能力的AI应用时&#xff0c;服务连续性是一个关键考量。单…...

深度学习在肺结节CT影像分析中的应用:从检测、分割到分类

1. 项目概述&#xff1a;从影像到洞察的智能跃迁在医学影像领域&#xff0c;尤其是胸部CT阅片&#xff0c;肺结节的检测、分割与分类一直是临床诊断的核心与难点。一个经验丰富的放射科医生每天需要面对数百甚至上千幅CT图像&#xff0c;在浩如烟海的二维切片中&#xff0c;精准…...

自托管知识库Lorex:基于现代Web技术栈的部署与架构解析

1. 项目概述与核心价值最近在折腾一个挺有意思的开源项目&#xff0c;叫 Lorex。这名字乍一听可能有点陌生&#xff0c;但如果你对构建一个功能齐全、界面现代的在线知识库或文档系统感兴趣&#xff0c;那它绝对值得你花时间研究。简单来说&#xff0c;Lorex 是一个基于 Web 的…...

太赫兹MIMO混合预编码与相位噪声抑制技术

1. 太赫兹混合预编码MIMO系统概述在无线通信领域&#xff0c;太赫兹频段&#xff08;90-300GHz&#xff09;因其巨大的连续带宽资源成为6G通信的关键技术方向。然而&#xff0c;这一频段面临严重的路径损耗和硬件实现挑战&#xff0c;特别是相位噪声问题。大规模MIMO技术通过部…...