1. モードの説明
シングルトン モードでは、クラスのインスタンスが 1 つだけ存在することが保証されます。オブジェクトを作成するとき、2 番目のオブジェクトを作成するときは、新しいオブジェクトではなく、すでに作成されているオブジェクトが取得されます。
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() を呼び出し、この時点でインスタンスが 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