デザインモードの美しさ--単例モード


なぜ単例を使用するのですか?
1つのクラスでは、1つのオブジェクトまたはインスタンスのみを作成できます.
背景紹介:マルチスレッドを使用して同じクラスに同時にアクセスするには、クラスのスレッドの安全を保証するために、2つの方法があります.
  • クラスは、インスタンス
  • のみを作成できる単一のモードとして定義される.
  • クラスのメンバー関数にクラスレベルのロックを追加する
  • 例:
    指定したファイルにログを書き込むクラスで、そのクラスが同時に呼び出されたときにファイルに書き込まれるログが上書きされないことを保証するために、以上の操作を実行する必要があります.
    単一のモデルのいくつかの古典的な実現方法:
  • 餓漢式はクラスのロード中に静的インスタンスを初期化するので、インスタンスの作成はスレッドが安全である.しかし、このような方法では、遅延ロードはサポートされず、インスタンスをロードするたびに再初期化され、オーバーヘッドが大きい.
  • 怠け者モードの空腹モードに対する利点は、遅延ロード(C++種の動的バインド)をサポートすることであり、このオブジェクトのインスタンスはインスタンス化された場合にのみ知られる.しかし、頻繁にロックが発生し、ロックが解放されると効率が低下するという問題が発生する.
  • 二重検出二重検出は、遅延負荷をサポートするとともに、高同時の単一の実装形態をサポートする.
  • 静的内部クラスJAVAがサポートする静的内部クラス実装の一例.この実装方式は,遅延負荷も高同時インスタンスもサポートし,二重検出よりも簡単に実現できる.
  • 列挙の最も簡単な実装形態は、列挙実装の一例に基づいている.列挙タイプ自体の特性により、インスタンスが作成するスレッドセキュリティとインスタンスの一意性が保証されます.

  • C言語単例モードの実現: csingleton.h
    #ifndef CSINGLETON_H
    #define CSINGLETON_H
    #include 
    
    typedef struct {
        void* (*ctor)(void *_self);
        void* (*dtor)(void *_self);
        void* (*createInstance)(void *self);
        void *instance;
    } _CSingleton;
    
    extern const void *CSingleton;
    void *GetInstance(void);
    
    #endif
    
    csingleton.c
    #include "csingleton.h"
    #include 
    
    
    static void *csingletonCtor(void *_self) {
        _CSingleton *self = _self;
    
        self->instance = _self;
        return self;
    }
    
    static void *csingletonDtor(void *_self) {
        _CSingleton *self = _self;
    
        self->instance = NULL;
        return self;
    }
    
    static void *csingletonCreateInstance(void *_self) {
        _CSingleton *self = _self;
    
        self->instance = _self;
        return self;
    }
    
    static _CSingleton _csingleton = {
        csingletonCtor, csingletonDtor, csingletonCreateInstance, NULL
    };
    const void *CSingleton = &_csingleton;
    
    void *GetInstance(void) { //                 
        if (NULL == ((_CSingleton*)CSingleton)->instance) {
            return csingletonCtor(CSingleton);
        } else {
            return ((_CSingleton*)CSingleton)->instance;
        }
    }
    
    main.c
    #include "csingleton.h"
    #include 
    
    int main(int argc, char *argv[]) {
        
    	void *ps1 = GetInstance();
        void *ps2 = GetInstance();
        if (ps1 == ps2) {
        	fprintf(stdout, "ps1 = ps2
    "
    ); } return 0; }
    #include 
    #include 
    #include 
    #include 
    #include 
    
    typedef struct ID{
    	char *name;
    	int id_num;
    }id;
    
    
    static id *_id = NULL;
    
    /*                  */
    static omp_lock_t lock;
    
    id *getInstance(){
    	omp_set_lock(&lock);
    	
    	if(NULL != _id) {
    		omp_unset_lock(&lock);
    		return _id;
    	} else {
    		_id = (id*)malloc(sizeof(id));
    		assert(_id != NULL);
    		omp_unset_lock(&lock);
    		return _id;
    	}
    }
    
    
    int main(int argc, char *argv[]) {
    	
    	omp_set_num_threads(20);//       ,         
    	id * i1, *i2;
    	
    	omp_init_lock(&lock);
    	{
            i1 = getInstance() ;
            i1->name = "Rong";
            i1->id_num = omp_get_thread_num();
    	}
    	 	
        {
            i2 = getInstance() ;
            i2->name = "Tao";
        }
    	omp_destroy_lock(&lock);
    	
    	if(i1 == i2){
    		fprintf(stdout, " i1 == i2 
    "
    ); } fprintf(stdout, "i1->name = %s, i1->score = %d
    "
    ,i1->name, i1->id_num); fprintf(stdout, "i2->name = %s, i2->score = %d
    "
    ,i2->name, i2->id_num); return 0; }

    C++実現単例モード
    #include 
    using namespace std;
    
    class Singleon
    {
    private:
    
    	Singleon()
    	{
    		cout << "Singleon()" << endl;
    	}
    
    	static Singleon* instance;
    public:
    	static Singleon* GetSingleon()
    	{
    		return instance;
    	}
        
    	static Singleon* Destroy()
    	{
    		delete instance;
    		instance = NULL;
    	}
    };
    
    /*            ,              */
    Singleon* Singleon::instance = new Singleon();
    
    int main()
    
    {
    	Singleon* sl1 = Singleon::GetSingleon();
    	Singleon* sl2 = Singleon::GetSingleon();
    	Singleon* sl3 = Singleon::GetSingleon();
    	cout << sl1 << endl;
    	cout << sl2 << endl;
    	cout << sl2 << endl;
    	system("pause");
    	return 0;
    
    }
    
    
    #include 
    using namespace std;
    
    class Singleon
    {
    private:
    	Singleon()
    	{
    		cout << "Singleon()" << endl;
    	}
    	static Singleon*instrance;
    public:
    	static Singleon* GetSingleon()
    	{
    		if (NULL == instrance)
    		{
    			instrance = new Singleon();
    			cout << "      " << endl;
    		}
    		else
    		{
    			cout << "        ,    " << endl;
    		}
    		return instrance;
    	}
    	static Singleon* Destroy()
    	{
    		delete instrance;
    		instrance = NULL;
    	}
    };
    
    /*            ,           */
    Singleon* Singleon::instrance =  NULL;
    int main()
    {
    	Singleon* sl1 = Singleon::GetSingleon();
    	Singleon* sl2 = Singleon::GetSingleon();
    	Singleon* sl3 = Singleon::GetSingleon();
    	cout << sl1 << endl;
    	cout << sl2 << endl;
    	cout << sl2 << endl;
    	system("pause");
    	return 0;
    }