Singletonパターンとは
クラスでインスタンスが1つしかなく,どこからでも値を持ったインスタンスを
取得することができるパターン
参照
Singleton何が悪いの?
【Singeltonパターン】考え方は単純だが、使いどころが大切なデザインパターン【コード例はRubyとJava】
シングルトンが邪悪な理由
シングルトンパターンの誘惑に負けない
クラス図
メリット
メリット
- メモリを節約できる
メモリを節約できる
インスタンスを,生成するとヒープ領域にインスタンス分のメモリが,割り当てられる.
それが,Singletonパターンの場合1回で済むのでメモリの節約になる
デメリット
- グローバル変数化する
- 状態を持ち続ける
- ユニットテストがしにくい
グローバル変数化する
インスタンスが1個で固定されていて,それが常に保有されている
そして,どこからでも変更ができるので,エラーの原因になったり,コードの複雑性に繋がったりする
状態を持ち続ける
グローバル変数と一緒なのだが,状態を持ち続けてしまうことで
どこかで,値を変えられた時に原因を突き止めるのが難しくなる.
ユニットテストがしにくい
理論的には独立しているはずのコード間に暗黙の依存関係を生んでしまう。これが問題なのは、まず依存関係が一見してわかりにくいからです。また、生まれてしまう依存関係は、本来不必要なはずです。問題の存在がはっきりするのは、ユニットテストの時です。ユニットテストは疎結合が前提となっていて、また「本物の」実装コードの代わりに、適宜モック(テスト用の偽者)実装に差し替えられることも重要だ、からです。シングルトンパターンはその妨げになるのです。
処理
Singleton
template <class T>
class Singleton
{
public:
static T& GetInstance(){
static T instance;
return instance;
}
protected:
Singleton() {};
virtual ~Singleton() {};
};
Test
#include<string>
#include"Singleton.h"
using namespace std;
class TEST1 :public Singleton<TEST1>
{
friend Singleton<TEST1>;
private:
TEST1() {};
~TEST1() {};
public:
void SetStr(const string str) { this->str = str; }
string GetStr()const { return str; }
private:
std::string str;
};
class TEST2 :public Singleton<TEST2>
{
friend Singleton<TEST2>;
private:
TEST2() {};
~TEST2() {};
public:
void SetStr(const string str) { this->str = str; }
string GetStr()const { return str; }
private:
std::string str;
};
Main
#include <iostream>
#include "Test.h"
using namespace std;
int main()
{
TEST1& test1 = TEST1::GetInstance();
test1.SetStr("test1");
//output: test1
cout << test1.GetStr() << endl;
TEST2& test2 = TEST2::GetInstance();
test2.SetStr("test2");
//output: test2
cout << test2.GetStr() << endl;
return 0;
}
実行結果
test1
test2