参考: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