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

news2024/11/28 10:43:54

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

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

相关文章

【从零开始学习Minio | 第一篇】快速介绍什么是Minio

前言&#xff1a; 在当今数字化时代&#xff0c;数据的存储和管理已经成为了企业发展中的关键一环。随着数据量的不断增长和数据安全性的日益受到重视&#xff0c;传统的数据存储解决方案往往面临着诸多挑战。为了应对这些挑战&#xff0c;云存储技术应运而生&#xff0c;并在…

【漏洞复现】CData API Server 路径遍历漏洞(CVE-2024-31849)

0x01 产品简介 CData API Server是CData公司的一个强大的数据连接平台&#xff0c;旨在帮助企业轻松地访问、整合和分析各种数据源。 0x02 漏洞概述 CData API Server 23.4.8846之前版本存在安全漏洞&#xff0c;该漏洞源于存在路径遍历漏洞。攻击者可利用该漏洞获得对应用程…

如何用TONGYILingma进行AI辅助编程?

通义灵码&#xff0c;是阿里云出品的一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码优化、注释生成、代码解释、研发智能问答、异常报错排查等能力&#xff0c;并针对阿里云的云服务使用场景调优&#xff0c…

[Maven]IDEA报错-xxx is referencing itself

在IDEA中&#xff0c;执行 mvn clean时报错xxx is referencing itself。 解决方案&#xff1a;https://stackoverflow.com/questions/64246267/maven-error-using-intellij-is-referencing-itself 具体做法&#xff1a;采用上图第二条&#xff0c;将父模块pom文件中的对子模块…

《十八》QThread多线程组件

本章将重点介绍如何运用QThread组件实现多线程功能。 多线程技术在程序开发中尤为常用&#xff0c;Qt框架中提供了QThread库来实现多线程功能。当你需要使用QThread时&#xff0c;需包含QThread模块&#xff0c;以下是QThread类的一些主要成员函数和槽函数。 成员函数/槽函数 …

Skywalking数据持久化与自定义链路追踪

学习本篇文章之前首先要了解一下Sky walking的基础知识 分布式链路追踪工具Skywalking详解 一&#xff0c;Sky walking数据持久化 Sky walking提供了es&#xff0c;MySQL等数据持久化方案&#xff0c;默认使用h2基于内存的数据库&#xff0c;重启之后数据即会丢失。 在实际工…

streamlit通过子目录访问

运行命令&#xff1a; streamlit hello 系统默认使用8501端口启动服务&#xff1a; 如果想通过子目录访问服务&#xff0c;可以这么启动服务 streamlit hello --server.baseUrlPath "app" 也可以通过以下命令换端口 streamlit hello --server.port 9999 参考&…

【每日刷题】Day33

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

error code [1449]; The user specified as a definer (‘root‘@‘%‘) does not exist

其实就是说我的root用户权限不够&#xff0c;那就要加上权限&#xff0c;网上其他地方也有好多处理办法&#xff0c;但是要注意数据库版本。我用的是MySQL8.0.32版本&#xff0c;我是这样处理的&#xff0c;简单可行&#xff1a; GRANT ALL ON *.* TO root% ;FLUSH PRIVILEGES…

关系型数据库MySQL开发要点之多表设计案例详解代码实现

什么是多表设计 项目开发中 在进行数据库表结构设计时 根据数据模型和业务关系 会根据业务需求和业务模块之间的关系分析设计表结构 由于业务之间互相关联 所以表结构之间也存在着各种联系 主要分为以下三种 一对多 每个部门下是有多个员工的 但是一个员工只能归属一个部…

Penpad再获 Presto Labs 投资,Scroll 生态持续扩张

​Penpad 是 Scroll 生态的 LaunchPad 平台&#xff0c;其整计划像收益聚合器以及 RWA 等功能于一体的综合性 Web3 平台拓展&#xff0c;该平台在近期频获资本市场关注&#xff0c;并获得了多个知名投资者/投资机构的支持。 截止到本文发布前&#xff0c;Penpad 已经获得了包括…

Excel数据分析之动态图表

在日常办公中&#xff0c;可以用透视表和切片器的组合方式&#xff0c;制作动态图&#xff0c;以直观的方式展示年度、季度&#xff0c;和不同区域的销售额。 通过结合使用这两个工具&#xff0c;您可以创建动态图表&#xff0c;可根据您的选择实时更新。这对于快速了解数据并…

【busybox记录】【shell指令】comm

目录 内容来源&#xff1a; 【GUN】【comm】指令介绍 【busybox】【comm】指令介绍 【linux】【comm】指令介绍 使用示例&#xff1a; 逐行比较两个排序后的文件 - 默认输出 逐行比较两个排序后的文件 - 如果一个文件的排序有问题&#xff0c;那么反错&#xff08;默认&…

IDEA中向Data Sources导入sql文件

IDEA中向Data Sources导入sql文件 开篇 在学习黑马的课程时&#xff0c;时常需要向数据库中导入sql文件生成数据库表&#xff0c;每次都会忘记导入步骤&#xff0c;折腾许久&#xff0c;于是将过程记录下来。 步骤 在Database中选择你要导入的数据库源&#xff0c;如图我想…

QT--1

类型界面 #include "mywidget.h"myWidget::myWidget(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(680,520);this->setFixedSize(680,520);this->setWindowTitle("Tim");this->setWindowFlag(Qt::FramelessWindowHint);th…

【牛客】【模板】差分

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 差分模板。 b[0]a[0]; b[1]a[1]-a[0]; b[2]a[2]-a[1]; ...... b[n-1]a[n-1]-a[n-2]; b[n]a[n]-a[n-1]; 差分标记&#xff1a;b[l]k,b…

数组折半法查找数据(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> //定义数据&#xff1b; #define N 15int main() {//初始化变量值&#xff1b;int a[N], i, top, bott, loca, flag 1, sign, numb…

Redis学习5——Redis应用之签到

Redis位图bitMap 位图由一系列二进制位组成&#xff0c;每个位可以被设置为1或0&#xff0c;当我们在处理需要高效存储和操作大量二进制位数据的适合&#xff0c;位图是一个非常有用的工具。 位图操作命令有&#xff1a; SETBIT&#xff1a;设置位图中指定位置的位的值。可以…

类加载器aa

一&#xff0c;关系图及各自管辖范围 &#xff08;不赘述&#xff09; 二&#xff0c;查看关系 package com.jiazai;public class Main {public static void main(String[] args) {ClassLoader appClassLoader ClassLoader.getSystemClassLoader();//默认System.out.println…

Debian是什么?有哪些常用命令

目录 一、Debian是什么&#xff1f; 二、Debian常用命令 三、Debian和CentOS的区别 四、Debian和CentOS的优缺点 五、Debian和CentOS的运用场景 一、Debian是什么&#xff1f; Debian是一种流行的开源Linux操作系统。 Debian是一个以Linux内核为基础的操…