C++设计模式代码--单例模式

参考:5. 单例模式(Singleton) (yuque.com)

1、什么是单例模式

保证一个类只有一个实例,并提供一个访问该实例的全局节点;

2、什么情况下需要单例模式

某个类的对象在软件运行之初就创建,并且在软件的很多地方都需要读写这个类的信息;使用单例模式的话,类对象就只要软件启动的时候创建一次,软件停止的时候释放;

3、优点

1)保证类只有一个实列;

2)有一个指向该实例的全局节点;

4、缺点

暂没经验

5、线程安全的懒汉单例模式
Singleton.h:
#ifndef SINGLETON_H_
#define SINGLETON_H_

#include <iostream>
#include <string>
#include <mutex>

// 配置类 
class SingletonConfig {
 public:
    static SingletonConfig* GetInstance() {
        if (instance_ == nullptr) {
            // 加锁保证多个线程并发调用getInstance()时只会创建一个实例
            m_mutex_.lock();
            if (instance_ == nullptr) {
                instance_ = new SingletonConfig();
            }
            m_mutex_.unlock();
        }
        return instance_;
    }
 private:
    SingletonConfig() {}
    static SingletonConfig* instance_;
    static std::mutex m_mutex_;
};

// 管理类
class SingletonManager {
 public:
    static SingletonManager* GetInstance() {
        if (instance_ == nullptr) {
            // 加锁保证多个线程并发调用getInstance()时只会创建一个实例
            m_mutex_.lock();
            if (instance_ == nullptr) {
                instance_ = new SingletonManager();
            }
            m_mutex_.unlock();
        }
        return instance_;
    }
 private:
    SingletonManager() {}
    static SingletonManager* instance_;
    static std::mutex m_mutex_;
};

#endif  // SINGLETON_H_
Singleton.cpp:
#include "Singleton.h"

// 静态变量instance初始化不要放在头文件中, 如果多个文件包含singleton.h会出现重复定义问题
SingletonConfig* SingletonConfig::instance_ = nullptr;
std::mutex SingletonConfig::m_mutex_;

SingletonManager* SingletonManager::instance_ = nullptr;
std::mutex SingletonManager::m_mutex_;
main.cpp
#include <iostream>
#include "Singleton.h"

int main() {
    SingletonConfig *s1 = SingletonConfig::GetInstance();
    SingletonConfig *s2 = SingletonConfig::GetInstance();

    std::cout << "s1地址: " << s1 << std::endl;
    std::cout << "s2地址: " << s2 << std::endl;

    SingletonManager *s3 = SingletonManager::GetInstance();
    SingletonManager *s4 = SingletonManager::GetInstance();

    std::cout << "s3地址: " << s3 << std::endl;
    std::cout << "s4地址: " << s4 << std::endl;

    return 0;
}
编译运行
$ g++ -g main.cpp Singleton.cpp -std=c++11 -o singleton
$ ./singleton 
s1地址: 0x5594b0f12e70
s2地址: 0x5594b0f12e70
s3地址: 0x5594b0f132a0
s4地址: 0x5594b0f132a0

此单例模式代码是比较常规的,使用和理解起来也方便,但是如果有多个类需要使用单例模式的话,那么每个类都需要定义一份单例类代码,这种情况下,进一步优化的话,可以定义单例类模板;

6、升级版:线程安全的懒汉单例类模板
Config.h
#ifndef CONFIG_H
#define CONFIG_H

#include "iostream"
#include "Singleton.h"

struct stuInfo{
    int index;
    std::string name;
    int age;
};

class Config
{
public:
    Config();
    ~Config();
    int getIndex() { return m_stuInfo.index; }
    std::string getName() { return m_stuInfo.name; }
    int getAge() { return m_stuInfo.age; }

    void init();
    void loadConfig();
    void syncConfig();

private:
    stuInfo m_stuInfo;
};

#define SingletonStuInfo    Singleton<Config>::GetInstance()

#endif // CONFIG_H
Singleton.h
#ifndef SINGLETON_H_
#define SINGLETON_H_

#include <iostream>
#include <string>
#include <mutex>

template <class T>
class Singleton {
 public:
    static T* GetInstance();

 private:
    Singleton() {}
    static T* m_instance;
    static std::mutex m_mutex;
};

template<class T>
T* Singleton<T>::m_instance = nullptr;
template<class T>
std::mutex Singleton<T>::m_mutex;

template <class T>
T* Singleton<T>::GetInstance() {
    if (m_instance == nullptr) {
        // 加锁保证多个线程并发调用getInstance()时只会创建一个实例
        m_mutex.lock();
        if (m_instance == nullptr) {
            m_instance = new T();
        }
        m_mutex.unlock();
    }
    return m_instance;
}

#endif  // SINGLETON_H_
Config.cpp
#include "Config.h"

Config::Config()
{

}

Config::~Config()
{

}

void Config::init()
{
    m_stuInfo.index = 0;
    m_stuInfo.name = "zhangsan";
    m_stuInfo.age = 20;
}

void Config::loadConfig()
{

}

void Config::syncConfig()
{

}

main.cpp
#include <iostream>
#include "Singleton.h"
#include "Config.h"

int main() {
    SingletonStuInfo->init();

    std::cout << "index: " << SingletonStuInfo->getIndex() << std::endl;
    std::cout << "name: " << SingletonStuInfo->getName() << std::endl;
    std::cout << "age: " << SingletonStuInfo->getAge() << std::endl;

    return 0;
}
编译运行
$ g++ -g main.cpp Singleton.cpp Config.cpp -std=c++11 -o singleton
$ ./singleton 
index: 0
name: zhangsan
age: 20

相关推荐

  1. C++设计模式代码--模式

    2023-12-29 14:52:02       40 阅读
  2. C++设计模式模式

    2023-12-29 14:52:02       37 阅读
  3. C++设计模式 -- (Singleton)模式

    2023-12-29 14:52:02       28 阅读
  4. c++设计模式模式

    2023-12-29 14:52:02       28 阅读
  5. C++ 设计模式模式

    2023-12-29 14:52:02       28 阅读
  6. C++设计模式-模式

    2023-12-29 14:52:02       20 阅读
  7. C++设计模式--模式

    2023-12-29 14:52:02       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-29 14:52:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-29 14:52:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-29 14:52:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-29 14:52:02       18 阅读

热门阅读

  1. IDEA快捷使用-快捷键&模板

    2023-12-29 14:52:02       38 阅读
  2. 【MySQL】mysql截取字符串函数的sql语句特殊处理

    2023-12-29 14:52:02       30 阅读
  3. 海豚调度 Dolphinscheduler-3.2.0 离线部署 伪集群模式

    2023-12-29 14:52:02       67 阅读
  4. Vue指令详解

    2023-12-29 14:52:02       35 阅读
  5. 深入了解Spring中的TaskScheduler

    2023-12-29 14:52:02       30 阅读
  6. Unity3D 如何提升游戏运行效率详解

    2023-12-29 14:52:02       36 阅读
  7. leetcode递增子序列、排列

    2023-12-29 14:52:02       30 阅读
  8. React函数组件使用Effect Hook(副作用钩子)

    2023-12-29 14:52:02       32 阅读
  9. react父组件props变化的时候子组件怎么监听?

    2023-12-29 14:52:02       38 阅读
  10. 【linux系统安装部署私有化的GitLab】

    2023-12-29 14:52:02       33 阅读
  11. 解除mobaxterm会话14个限制

    2023-12-29 14:52:02       36 阅读
  12. 【Qt】Qt中通过QProcess::execute()调用echo命令不生效

    2023-12-29 14:52:02       31 阅读