1. 模式说明
单例模式保证类只有一个实例;创建一个对象,当你创建第二个对象的时候,此时你获取到的是已经创建过的对象,而不是一个新的对象;
1.1 使用场景
共享资源的访问权限;任务的管理类;数据库的操作等;
1.2 要素
- 私有化类的构造函数;
- 使用类的私有静态指针变量指向类的唯一实例
- 公有静态方法获取该实例;
1.3 类型
- 懒汉模式
- 饿汉模式
2. 懒汉模式
单例实例在第一次被使用时才进行初始化,延迟初始化
2.1 基本
示例
/*
* @brief : design patterns singleton
* @author : your name
* @compile : g++ -g singleton_main.cc -o d -std=c++11
* @date : 2023/04/18
* @lastEditorDate:
*/
#include <iostream>
#include <string>
//懒汉模式
class Singleton
{
public:
static Singleton* getSingletonInstance() //访问函数
{
if(instance == nullptr)
{
instance = new Singleton;
}
return instance;
}
public:
void addCount() {
m_count++;
}
int32_t getCount() {
return m_count;
}
private:
static Singleton* instance; //静态指针变量
Singleton(){} //私有化类的构造函数
int32_t m_count{0};
};
Singleton* Singleton::instance = nullptr; //静态成员类外初始化
int main(int argc, char* argv[])
{
Singleton* single_0 = Singleton::getSingletonInstance();
single_0->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;
Singleton* single_1 = Singleton::getSingletonInstance();
single_1->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;
return 0;
}
输出
single_0 value is: 1
single_0 value is: 2
single_1 value is: 2
2.2 线程安全
2.1中的示例是线程不安全的,假如有多个线程同时调用getSingletonInstance(),此时检测到instance是nullptr,就会导致单例的崩溃,造成内存泄漏;
通过加锁来实现
示例
/*
* @brief : design patterns singleton
* @author : your name
* @compile : g++ -g singleton_main.cc -o d -std=c++11
* @date : 2023/04/18
* @lastEditorDate:
*/
#include <iostream>
#include <string>
#include <mutex>
//懒汉模式
std::mutex mtx; //全局的锁
class Singleton
{
public:
static Singleton* getSingletonInstance() //访问函数
{
if(instance == nullptr)
{
std::lock_guard<std::mutex> guard(mtx);
if(instance == nullptr)
{
instance = new Singleton;
}
}
return instance;
}
public:
void addCount() {
m_count++;
}
int32_t getCount() {
return m_count;
}
private:
static Singleton* instance; //静态指针变量
Singleton(){} //私有化类的构造函数
int32_t m_count{0};
};
Singleton* Singleton::instance = nullptr; //静态成员类外初始化
int main(int argc, char* argv[])
{
Singleton* single_0 = Singleton::getSingletonInstance();
single_0->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;
Singleton* single_1 = Singleton::getSingletonInstance();
single_1->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;
return 0;
}
输出
single_0 value is: 1
single_0 value is: 2
single_1 value is: 2
使用 c++11 中局部静态变量是线程安全的性质
示例
/*
* @brief : design patterns singleton
* @author : your name
* @compile : g++ -g singleton_main.cc -o d -std=c++11
* @date : 2023/04/18
* @lastEditorDate:
*/
#include <iostream>
#include <string>
#include <mutex>
//懒汉模式
class Singleton
{
public:
static Singleton* getSingletonInstance() //访问函数
{
static Singleton instance; //静态指针变量
return &instance;
}
public:
void addCount() {
m_count++;
}
int32_t getCount() {
return m_count;
}
private:
Singleton(){} //私有化类的构造函数
int32_t m_count{0};
};
int main(int argc, char* argv[])
{
Singleton* single_0 = Singleton::getSingletonInstance();
single_0->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;
Singleton* single_1 = Singleton::getSingletonInstance();
single_1->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;
return 0;
}
输出
single_0 value is: 1
single_0 value is: 2
single_1 value is: 2
3. 饿汉模式
指单例实例在程序运行时被立即执行初始化
示例
/*
* @brief : design patterns singleton
* @author : your name
* @compile : g++ -g singleton_main.cc -o d -std=c++11
* @date : 2023/04/18
* @lastEditorDate:
*/
#include <iostream>
#include <string>
#include <mutex>
//饿汉模式
class Singleton
{
public:
static Singleton* getSingletonInstance() //访问函数
{
return instance;
}
public:
void addCount() {
m_count++;
}
int32_t getCount() {
return m_count;
}
private:
static Singleton* instance; //静态指针变量
Singleton(){} //私有化类的构造函数
int32_t m_count{0};
};
Singleton* Singleton::instance = new Singleton; //静态成员类外初始化
int main(int argc, char* argv[])
{
Singleton* single_0 = Singleton::getSingletonInstance();
single_0->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl<<std::endl;
Singleton* single_1 = Singleton::getSingletonInstance();
single_1->addCount();
std::cout<<"single_0 value is: "<<single_0->getCount()<<std::endl;
std::cout<<"single_1 value is: "<<single_1->getCount()<<std::endl<<std::endl;
return 0;
}
输出
single_0 value is: 1
single_0 value is: 2
single_1 value is: 2
4. 在开发过程中的使用
在项目的使用过程中,可以将单例设计成为类模板;这样其它类在设计的时候不用考虑,是否需要将其设计成为单例;
其它类如果需要单例属性,只需要通过单例模板对其进行赋能即可;
示例
/*
* @brief : design patterns singleton
* @author : your name
* @compile : g++ -g singleton_main.cc -o d -std=c++11
* @date : 2023/04/18
* @lastEditorDate:
*/
#include <iostream>
#include <string>
#include <mutex>
template<class T>
class Singleton
{
public:
static T* getSingletonInstance() //访问函数
{
static T instance; //静态指针变量
return &instance;
}
private:
Singleton(){} //私有化类的构造函数
};
class C1
{
public:
void addCount() {
m_count++;
}
int32_t getCount() {
return m_count;
}
private:
int32_t m_count{0};
};
int main(int argc, char* argv[])
{
auto re1 = Singleton<C1>::getSingletonInstance();
re1->addCount();
std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;
auto re2 = Singleton<C1>::getSingletonInstance();
re2->addCount();
std::cout<<"re1->getCount() value is: "<<re1->getCount()<<std::endl;
std::cout<<"re2->getCount() value is: "<<re2->getCount()<<std::endl;
return 0;
}
输出
re1->getCount() value is: 1
re1->getCount() value is: 2
re2->getCount() value is: 2