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

C++设计模式之:单例模式singleton

摘要:

   it人员无论是使用哪种高级语言开发东东,想要更高效有层次的开发程序的话都躲不开三件套:数据结构,算法和设计模式。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

   设计模式坚持七大原则:开闭原则,单一职责原则,里氏替换原则,依赖倒转原则,接口隔离原则,迪米特原则,合成复用原则,而各项设计模式又区分为三大模式,创建型模式,结构型模式,行为模式。

   此系列专注讲解C++开发过程中高需求好用的设计模式类型,能更好的简练项目架构和代码量,通过使用场景以及代码实现来更好的介绍。本文介绍的是单例模式singleton。

(开发环境:VSCode,GCC13.2.0,cmake3.8)

关键词C++设计模式单例模式Design patternsingleton

声明:本文作者原创,转载请附上文章出处与本文链接。

文章目录

      • 摘要:
      • 正文:
        • 介绍
        • 使用场景
        • 注意事项
        • 代码实现
      • 推荐阅读

正文:

介绍

   单例模式(Singleton Pattern)是一种常用的软件设计模式,这种类型的设计模式属于创建型模式,其目的确保一个类仅有一个实例,并提供一个访问它的全局访问点。这种模式在需要控制资源访问、实现配置文件的读取或者管理数据库连接等场景下非常有用。

使用场景

   正如一个项目一个系统内,只会有一个日志,一个数据中台,一个数据库一个IO一样,把这些模块设计成单例模式可避免对资源的多重占用,减少内存的开销,提高代码可读性和复用性。

   在C++中单例或许可以等式于全局变量+命名空间,如果不是为复杂抽象业务,也可以简单用全局变量实现。

   单例虽好但现实也有存在很多滥用单例的情况,比如只是以需要一个全局变量为由加了一个单例类,为避免这种情况最好就是特殊模块用单例(做成库),加创建一个命名空间内放置零散的全局变量,函数。

注意事项
  • 确保类只有一个实例,并提供一个全局访问点。
  • 在多线程环境下,确保单例的唯一性,也即是线程安全。
  • 要注意定义与声明分离,不然打包成库引用的话可能会有定义bug。
代码实现

单例模式可以分为懒汉式饿汉式,两者之间的区别在于创建实例的时间不同。

  • 懒汉式:延迟加载,即在第一次使用时才创建实例。
  • 饿汉式:类加载时就完成实例的初始化,确保线程安全但可能会浪费资源。

   比较多的是用lazy_load懒汉式然后加锁保证线程安全,懒汉式常用的两种方式加锁,一种互斥锁mutex,另一种使用call_once。使用互斥锁mutex来给单例加锁的方法是确保同一时刻只能有一个线程取得该锁,其他试图取得该锁的线程阻塞,待持有锁的线程释放独占锁时,才能唤醒取得独占锁后继续运行,而call_once则是在多线程环境中,确保某个对象只初始化一次,更推荐使用call_once

懒汉式(线程安全,使用互斥锁mutex)

#pragma once
#include <mutex>
#include <iostream>

class Singleton 
{
public:
    // 防止拷贝
	Singleton() = default;
	Singleton(const Singleton&) = default;
	Singleton& operator=(const Singleton&) = default;

    static Singleton* GetInstance()
    {
        // 创建-使用数据库单例,双重锁定
        if (singleton == nullptr) {
            std::unique_lock<std::mutex> lock(mtx);
            if (singleton == nullptr) {
                singleton = new Singleton();
                singleton->_InitData();
            }
        }
        return singleton;
    }
    //释放资源
	static void Release()
	{
        if (singleton != NULL) {
			delete singleton;
			singleton = NULL;
		}
    }
    
    // 成员函数
	// ……

private:
    //初始化数据
	void _InitData();
    
    static Singleton* singleton;
    static std::mutex mtx;
};

Singleton* Singleton::singleton = nullptr;
std::mutex Singleton::mtx;

懒汉式(线程安全,使用call_once)

#pragma once
#include <mutex>
#include <iostream>

class Singleton
{
public:
    // 防止拷贝
	Singleton() = default;
	Singleton(const Singleton&) = default;
	Singleton& operator=(const Singleton&) = default;

	// 创建-使用数据库单例 lazy_load
	static Singleton* GetInstance()
	{
		static std::once_flag s_flag;
		std::call_once(s_flag, [&]()
			{
				singleton = new Singleton();
				singleton->_InitData();
			});
		return singleton;
	}
	// 释放资源
	static void Release()
	{
		if (singleton != NULL) {
			delete singleton;
			singleton = NULL;
		}
	}
	
    // 成员函数
	// ……

private:
	//初始化数据
	void _InitData();

	static Singleton* singleton;
	std::unordered_map<std::string, ISSUEDATA> data;	
};

Singleton* Singleton::singleton = NULL;

over~

推荐阅读

博客主页:https://blog.csdn.net/weixin_45068267
(客官逛一逛,有许多其它有趣的专栏博文)

C/C++专栏:https://blog.csdn.net/weixin_45068267/category_12268204.html
(内含其它设计模式的介绍和实现)


http://www.kler.cn/a/294413.html

相关文章:

  • Sigrity SPEED2000 Power Ground Noise Simulation模式如何查看PDS系统的自阻抗操作指导
  • 28.医院管理系统(基于springboot和vue)
  • wafw00f源码详细解析
  • 【Elasticsearch入门到落地】1、初识Elasticsearch
  • 扫雷游戏代码分享(c基础)
  • 【Linux篇】面试——用户和组、文件类型、权限、进程
  • HTTP 一、基础知识
  • iOS18 beta版本怎么回退至iOS17正式版本?
  • 软考(计算机技术与软件专业技术资格(水平)考试)
  • StyleGAN——生成风格化的视频内容,特别是在艺术视频或动画领域,可以将视频的视觉风格转换为特定的艺术风格
  • 鸿蒙MPChart图表自定义(四)短刻度线
  • GIT-macOS配置推送代码到GitHub
  • VMware Fusion Pro 13 for Mac虚拟机软件
  • 人体红外传感器简介
  • css实现卡片右上角的状态
  • 多波束EM2040D以及POSMV使用记录
  • 使用Django身份验证系统
  • Ai+若依(智能售货机运营管理系统---帝可得)-人员管理-点位管理-区域管理-合作商管理----【08篇---0001:上】
  • 打造个性化时装购物平台:Spring Boot框架的实践
  • 计算机基础知识复习9.6
  • 实战项目:俄罗斯方块(七)
  • 点云数据常见的坐标系有哪些,如何进行转换?
  • sql-labs61-65关通关攻略
  • 数据仓库技术选型方案文档
  • vue----一维数组根据同一id改成二维数组
  • WPF入门到跪下 第十一章 Prism(四)View与ViewModel的自动关联