【C/C++】设计模式——单例模式

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
🔥c++系列专栏:C/C++零基础到精通 🔥

给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ

在这里插入图片描述

c语言内容💖:

专栏:c语言之路重点知识整合

【c语言】全部知识点总结


目录

  • 单例模式
  • 饿汉式单例模式
  • 懒汉式单例模式
  • 单例模式的优缺点
    • 优点
    • 缺点
  • 应用示例

单例模式

单例模式确保了一个类只有一个实例,并提供一个全局访问点来获取这个实例。

单例模式的特点:

  • 1.一个类只有一个实例
  • 2.提供一个全局访问点来获取这个实例
  • 3.单例对象必须由单例类进行创建(构造函数设为私有 private)

如何实现单例模式?

构造析构拷贝构造私有
提供静态公有的获取对象的方法

image.png

饿汉式单例模式

在类刚开始加载的时候就创建好对象,不会出现线程安全问题

#include <iostream>
using namespace std;class Singleton
{
private:// 静态成员变量在类声明时就已经初始化  static Singleton* sin;// 私有构造函数,确保外部无法直接创建实例  Singleton(){}Singleton(const Singleton& single) = delete;  // 使用delete替代私有构造函数// 析构函数也设置为私有,但这在饿汉式单例中不是必需的,因为对象是在程序结束时自动销毁的	~Singleton(){}public:static Singleton* getSingle(){// 直接返回已经初始化的静态对象的地址  return sin;}void fun(){cout << "Singleton::fun()" << endl;}};
// 在类外初始化静态成员变量  
Singleton* Singleton::sin = new Singleton();int main()
{//获取单例对象Singleton* single1 = Singleton::getSingle();single1->fun();getchar();return 0;
}

在类被加载时就被初始化为一个指向新创建的Singleton对象的指针。

因此,无论何时调用Singleton::getSingle(),它都会返回同一个对象的地址。

在程序结束时,这个静态的Singleton对象会被自动销毁

懒汉式单例模式

类加载时没有生成单例,而是在第一次调用获取实例的方法时才去创建这个单例。 会出现线程安全问题,即当多个线程同时访问某个对象或数据时,可能导致数据的不一致或错误

#include <iostream>
using namespace std;class Singleton
{
private:static Singleton* sin;Singleton(){}Singleton(const Singleton& single) = delete;  // 使用delete替代私有构造函数~Singleton(){}public:static Singleton* getSingle(){if (sin == nullptr) // 如果单例对象还未被创建  {sin = new Singleton(); // 创建单例对象  }return sin;}void fun(){cout << "Singleton::fun()" << endl;}};
Singleton* Singleton::sin = nullptr;int main()
{//获取单例对象Singleton* single1 = Singleton::getSingle();single1->fun();getchar();return 0;
}

单例模式的优缺点

优点

  1. 控制资源访问:通过单例模式,可以确保对某个资源的全局访问点只有一个,这样可以防止其他对象对该资源的访问导致状态不一致或数据污染。
  2. 减少系统开销:如果一个类的实例创建非常消耗资源(如读取配置文件、打开数据库连接等),使用单例模式可以确保系统只创建一个实例,从而减少系统开销。
  3. 简化配置:在单例模式中,由于类的实例是预先创建好的,因此在系统启动时就可以加载和初始化,这样可以简化配置和初始化工作。
  4. 便于管理:由于单例模式提供了全局访问点,因此可以很方便地对实例进行管理和维护
  5. 避免对象之间的直接耦合:使用单例模式可以避免对象之间的直接耦合,而是通过单例类来协调它们之间的关系。

缺点

  • 在多线程下,懒汉式单例模式可能会引起线程安全问题
  • 由于单例模式的本质是将类的实例化控制权交由类本身来管理,因此难以扩展。如果需要为单例类添加新的功能,可能需要修改原有的代码,这可能会违反开闭原则
  • 单例模式可能会将多个功能放在同一个类中,这可能会违反单一职责原则

应用示例

在使用 mysql 对象操作某个数据库中中,通常只使用一个 mysql 对象,对数据库进行复用连接,而不是为每个请求都创建一个新的连接

GetInstance 方法是获取单例实例的公共静态方法,使用 std::call_once 来确保线程安全地初始化单例实例

#include <mysql.h>  
#include <string.h>  
#include <iostream>  
#include <list>  
#include <mutex>  using namespace std;  class CMySql  
{  
private:  CMySql() {}  // 私有构造函数,防止外部使用 new 关键字创建实例  CMySql(const CMySql&) = delete;  // 删除拷贝构造函数  CMySql& operator=(const CMySql&) = delete;  // 删除赋值运算符  public:  static CMySql& GetInstance() {  std::call_once(initInstanceFlag, &InitSingleton);  return *m_pInstance;  }  public:  ~CMySql(void);  bool ConnectMySql(const char* host, const char* user, const char* pass, const char* db, short nport = 3306);  void DisConnect();  bool SelectMySql(char* szSql, int nColumn, list<string>& lstStr);  bool GetTables(char* szSql, list<string>& lstStr);  bool UpdateMySql(char* szSql);  private:  static CMySql* m_pInstance;  // 静态私有成员变量,保存类的唯一实例  static std::once_flag initInstanceFlag;  // 用于确保线程安全的初始化  MYSQL* m_sock;  MYSQL_RES* m_results;  MYSQL_ROW m_record;  // 初始化单例的函数  static void InitSingleton() 
{  m_pInstance = new CMySql();  }  
};  // 初始化静态成员变量  
CMySql* CMySql::m_pInstance = nullptr;  
std::once_flag CMySql::initInstanceFlag;  // 析构函数  
CMySql::~CMySql() 
{  // 清理资源等操作  
}  

在这里插入图片描述

大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●)

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

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

相关文章

创意无限,批量剪辑技巧:视频剪辑中的画中画技巧大揭秘

在视频剪辑的世界里&#xff0c;创意是无限的&#xff0c;而技巧则是实现这些创意的关键。画中画技巧作为视频剪辑中的一种高级技术&#xff0c;可以带给观众新颖的视觉体验&#xff0c;提升视频的质量和观赏性。本文将深入探讨批量剪辑中的画中画技巧&#xff0c;揭示其背后的…

分布式与一致性协议之ZAB协议(五)

ZAB协议 ZAB集群如何从故障中恢复 如果我们想把ZAB集群恢复到正常状态&#xff0c;那么新领导者就必须确立自己的领导关系&#xff0c;成为唯一有效的领导者&#xff0c;然后作为主节点"领导"各备份节点一起处理读写请求 如何确立领导关系 前面提到&#xff0c;选…

Python-VBA函数之旅-property函数

目录 一、property函数的常见应用场景 二、property函数使用注意事项 三、如何用好property函数&#xff1f; 1、property函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、prop…

Backblaze发布2024 Q1硬盘故障质量报告-1

作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告&#xff0c;给大家提供了一份真实应用场景下的稳定性分析参考数据。 截至2024年第一季度末&#xff0c;Backblaze在其全球数据中心的云存储服务器…

嵌入式开发常见概念简介

目录 0. 《STM32单片机自学教程》专栏总纲 API Handle(句柄) 0. 《STM32单片机自学教程》专栏总纲 本文作为专栏《STM32单片机自学教程》专栏其中的一部分&#xff0c;返回专栏总纲&#xff0c;阅读所有文章,点击Link: STM32单片机自学教程-[目录总纲]_stm32 学习-CSD…

HCIP的学习(OSPF总篇)

HCIA的复习 这边可以与我之前写的HCIA博客结合起来一起看&#xff0c;效果更好 HCIA的学习&#xff08;6&#xff09; OSPF状态机 down—关闭-----一旦启动OSPF进程&#xff0c;并发出hello报文&#xff0c;则进入下一个状态init----初始化状态------当收到的hello报文中存在…

太阳能光伏在生活中的三大作用

随着现在太阳能光伏的逐步发展&#xff0c;太阳能光伏已经越来越走近人们的生活&#xff0c;小编带大家盘点一下光伏在生活中的应用 一、发电 光伏的最初应用就是用来发电&#xff0c;以替代传统的化石燃料发电方式。光伏发电可以从根本上解决当今社会面临的能源短缺问题&…

GhostNetV2 Enhance Cheap Operation with Long-Range Attention 论文学习

论文地址&#xff1a;https://arxiv.org/abs/2211.12905 代码地址&#xff1a;https://github.com/huawei-noah/Efficient-AI-Backbones/tree/master/ghostnetv2_pytorch 解决了什么问题&#xff1f; 在计算机视觉领域&#xff0c;深度神经网络在诸多任务上扮演着重要角色。为…

数据结构(c):队列

目录 &#x1f37a;0.前言 1.什么是队列 2. 队列的实现 2.1定义队列节点 2.2定义队列 2.3队尾入队列 2.4判断队列是否为空 2.5队头出队列 2.6 队列首元素 2.7队尾元素 2.8队列内的元素个数 2.9销毁队列 3.试运行 &#x1f48e;4.结束语 &#x1f37a;0.前言 言C之…

揿针有危险吗?

点击文末领取揿针的视频教程跟直播讲解 揿针是一种特殊的针具&#xff0c;具有一定的危险性&#xff0c;可能会导致局部感染、疼痛、出血、神经损伤、气胸等危害。 具体体现在什么地方呢&#xff1f; 1、局部感染如果在进行揿针治疗时&#xff0c;没有严格进行无菌操作&#…

【每日刷题】Day33

【每日刷题】Day33 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 2. 445. 两数相加 II - 力扣&#xff08;…

uniapp 监听APP切换前台、后台插件 Ba-Lifecycle

监听APP切换前台、后台 Ba-Lifecycle 简介&#xff08;下载地址&#xff09; Ba-Lifecycle 是一款uniapp监听APP切换前台、后台的插件&#xff0c;简单易用。 截图展示 也可关注博客&#xff0c;实时更新最新插件&#xff1a; uniapp 常用原生插件大全 使用方法 在 script…