作成型モードの単品モード(Singleton Pattern)C++実装

5868 ワード

Singleton Pattern作成型モード
定義:クラスにインスタンスが1つしかないことを確認し、グローバル・アクセス・ポイントを提供します.
ユニークでインスタンスが1つしかないオブジェクトを作成するための入場券.これはすべての設計モードクラス図の中で最も簡単です.このモデルは開発において非常に有用である.
単一モードを実現するには、プライベートコンストラクタ、静的方法、および静的変数が必要です.
このモードは、オブジェクトを作成するために1つのファクトリしか必要としないため、抽象ファクトリモードまたはファクトリモードと組み合わせて使用されます.
このモードは最も簡単で、C++の実現は以下の通りである.
Singleton.hヘッダファイルは以下の通りである.
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* Instance();//                ,     ,        delete ,  reference    。
protected:
Singleton(); //     private
Singleton(const Singleton&);//copy                  

Singleton& operator=(const Singleton&);//      Singleton           ,         Singleton  。       。
static Singleton* _instance;
};


#endif

Singleton.CPPソースファイル
#include"Singleton.h"
#include <iostream>
using namespace std;

Singleton * Singleton::_instance=0;
Singleton::Singleton(const Singleton &rhs){}
Singleton::Singleton()
{
	cout<<"Singleton....."<<endl;
}
Singleton * Singleton::Instance()
{
 if(_instance==0)
	 _instance=new Singleton();
 
 return _instance;

}

メイン関数main.CPP
#include"Singleton.h"
#include <iostream>
using namespace std;

int main(int argc,char *argv[])
{
	Singleton * sgn = Singleton::Instance();
	return 0;
}

単品モードのいくつかの問題:
1.Singletonの破棄
Singletonは、必要に応じて生成されます.つまり、Instance()が最初に呼び出されたときに生成されるので、構造時間が決定されますが、構造問題は解決されません.Singletonはいつ自分のエンティティを破棄すべきですか.実際にSingletonが破棄されていなくてもメモリが漏れることはなく、リソースが漏れることがあります.これはSingleton構造関数が広範なリソースを求めることができるためである:ネットワーク接続、OS反発体(mutexes)、およびプロセス通信方法における様々なhandles待ち.リソース漏洩を回避する唯一の正しい方法は、プログラムの終了時または終了時にSingletonオブジェクトを削除することです.Singletonオブジェクトが破壊された後に使用されないように、削除のタイミングを慎重に選択する必要があります.Singletonを破壊する最も簡単な方法は言語メカニズムに依存することである.Singleton&Singleton::Instance(){static Singleton obj;//関数内のstaticオブジェクトがこの関数の最初の実行時に初期化されます.return obj;}
int Fun(){static int x=100;//コンパイラ定数で初期化し、Fun()が最初に呼び出される前にxはとっくに100に設定されていた.return++x;}
2.無効なSingletonオブジェクト参照の問題プログラムで関連するSingletonsが複数使用されている場合、寿命を制御するための自動メソッドは提供されません.1つの合理的なSingletonは少なくともdead-reference検出を実行すべきである.これを行うには、メンバー変数static boolを宣言します.destoryedは、初期値がfalseである解析的挙動を追跡する.構造関数はそれを真に設定します.void Singleton::OnDeadReference(){throw std::runtime_error("無効な参照");}
3.押し潰したSingletonオブジェクトを復活させる
どのようにして破壊されたSingletonオブジェクトを復活させ、いつでもSingletonオブジェクトが唯一のエンティティであることを保証します.dead referenceが検出された場合、エンティティを再構築できます(C++は、静的オブジェクトのメモリがプログラムのライフ期間全体にわたって保持されるため、この機能を保証します).この新しいオブジェクトの構造関数をatexit()で登録できます.
class Singleton { void KillSingleton(); } void Singleton::OnDeadReference() { Create(); new(_instance) Singleton; atexit(KillSingleton); Destoryed=false; } void Singleton::KillSingleton() { _instance->~Singleton();
}
4.修正後の単品モードを実現する:
PhSingleton.hヘッダファイル
 
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton& Instance();

protected:
Singleton(); //     privated
Singleton(const Singleton &);
Singleton &operator=(const Singleton&);
virtual ~Singleton(); //      ,  Singleton            
private:
 static void Create();
 static void OnDeadReference();
 static void KillSingleton();
 static Singleton* _instance;
static bool _destoryed;
};

#endif


 
PhSingleton.CPPソースファイル
#include"PhSingleton.h"
#include <iostream>
using namespace std;
Singleton * Singleton::_instance=0;
bool Singleton::_destoryed=false;
Singleton::Singleton()
{
 cout<<"PhSingleton....."<<endl;
}
Singleton& Singleton::Instance()
{
 if(!_instance) 
 {
  if(_destoryed) //        
  {
   OnDeadReference(); //    
  }
  else
  {
   Create();//       
  }

 }
 return *_instance;
}
void Singleton::Create()
{ 
 //   _instance
static Singleton theInstance;
_instance=&theInstance;

}
void Singleton::KillSingleton()
{
 _instance->~Singleton();
}
void Singleton::OnDeadReference()
{
 //throw std::runtime_error("    ");
 Create();
 new(_instance) Singleton; //          Singleton,    ,    
 atexit(KillSingleton);//atexit()   C     ,                   
                      //         LIFO;new delete            。
 _destoryed=false;
}
Singleton::~Singleton()
{
 _instance=0;
 _destoryed=true;
}


主調関数:main.cpp
#include "PhSingleton.h"
#include <iostream>
using namespace std;
int main(int argc,char* argv[])
{
  Singleton *sgn =&Singleton::Instance();
 
 Singleton *sgn1=&Singleton::Instance();
 if(sgn==sgn1)
       cout<<"The same instance..."<<endl;
 /*if(sgn)
  delete sgn;*///       protected   ingleton::~Singleton: 
 return 0;

}


上の単品モードのイベントフロー:プログラム終了中にSingleton解析関数が呼び出され、ポインタを0にリセットして_destoryedはtrueに設定されます.グローバルオブジェクトがSingletonを再使用しようとすると、Instance()はOnDeadReference()を呼び出し、接尾辞はSingletonを復活させ、KillSingleton()を登録し、Instance()は合法的なreferenceが再生したSingletonオブジェクトを指すことに成功します.