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

ops/2024/10/18 8:32:38/

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡>𖥦<)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
🔥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.ppmy.cn/ops/36709.html

相关文章

stm32芯片外设

STM32 F1系列微控制器是ST公司推出的一系列基于ARM Cortex-M3内核的微控制器。这一系列微控制器拥有丰富的外设资源&#xff0c;包括但不限于&#xff1a; ADC&#xff08;模数转换器&#xff09;&#xff1a;用于将模拟信号转换为数字信号&#xff0c;通常用于传感器数据的读取…

外网禅道配置

exportfs -avrf 修改代码&#xff0c;避免启动太慢&#xff1a;vi /opt/zbox/bin/zbox.php 启动和停止 /opt/zbox/zbox start /opt/zbox/zbox stop

基于51单片机的ADC0804的电压表设计(仿真+源码+设计资料)

目录 1、前言 2、资料内容 3、仿真图 4、程序 资料下载地址&#xff1a;基于51单片机的ADC0804的电压表设计&#xff08;仿真源码设计资料&#xff09; 1、前言 最近看网上有很少的ADC0804的设计了&#xff0c;都由0809代替&#xff0c;但是有个别因为成本原因和学校课…

Spring Boot集成RabbitMQ-之6大模式总结

A.集成 一&#xff1a;添加依赖 在pom.xml文件中添加spring-boot-starter-amqp依赖&#xff0c;以便使用Spring Boot提供的RabbitMQ支持&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp&…

第6章:6.4.4 MATLAB爬虫的局限性和注意事项 (MATLAB入门课程)

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 使用MATLAB爬虫时&#xff0c;有几个局限性和注意事项需要我们留…

java—异常

异常 什么是异常 异常的体系 编译时异常处理方式 1、选择报错的整个代码块&#xff0c;快捷键crtlaltt键&#xff0c;选择try/catch将代码围起来。 2、编译异常处理方式2 在main方法上抛出异常 自定义异常 例子&#xff1a; 自定义运行时异常 自定义编译时异常 异常…

面试官:打开了一个新窗口,怎么知道这个窗口已经被打开过?

前言 我们现在来想这么一个场景,在掘金的文章管理页打开了一篇文章草稿,然后点击编辑,这个时候打开新标签页 A ,再点击一次编辑,打开了标签页 B 。 此时如果你在 A 编辑, B 是感知不到 A 的内容变动的,因为没做协同编辑。此时再到 B 编辑,那么就可能导致A标签页的内容…

期权扫盲贴:基础知识汇总,如何开通低佣期权账户(建议收藏)

一、什么是场内期权&#xff1f; 场内期权&#xff0c;也被称为交易所期权&#xff0c;是指在证券交易所内进行交易的标准化期权合约。 场内期权的交易是由证券交易所发布和监管的&#xff0c;具有统一的合约规格和交易规则&#xff0c;因此方便投资者进行交易。 以中国证券…