關於composition與singleton的爭論(?)

 

最近與公司同事討論到了這兩種方式的使用時機,請看以下狀況:

 

當我們提到composition的時候,主要是要拿來維持各個物件中的階層關係,以及讓物件的歸屬更為清楚。

 

class A
{
public:
    A()
{};
    
~A(){};
private:
}
;


class B
{
public:
    B()
{m_poA = new A;};
    
~B(){delete m_poA;};
private:
    A
* m_poA;
}
;

 

依以上的程式碼來看,class B在construct時便會建立一個A物件,而在B destruct時,A也會一同消失。

那麼現在來看看另外一種可以達到同樣目的寫法:

 

class C
{
public:
    C()
{m_poInstance = NULL;};
    
~C();

    
static C* GetInstance()
    
{
        
if(!m_poInstance)
        
{
            m_poInstance 
= new C;
        }

    }
;

    
void Release()
    
{
        delete m_poInstance;
    }
;

    
void Init(){};

private:
    
static C* m_poInstance;
}
;


class B
{
public:
    B()
    
{
        C::GetInstance()
->Init();
    }
;

    
~B()
    
{
        C::GetInstance()
->Release();
    }
;

private:
}
;

 

 

這次以singleton的寫法,來實作剛才的需求:B在destruct時,裡面的member也必須一併destruct。

 

根據同事的說法,兩種方法的不同點,在於第一種是遵循OO法則,class裡面的member很清楚歸屬於誰,該生成就生成,該消滅就消滅,並不會有模糊地帶。

而第二種方式等於是一個全域變數,使用者不管在何時何地呼叫,都會保證該class一定存在,等於是破壞了OO的法則。

 

這邊我提出一些看法,我覺得這兩種方式在結果上並無不同。第一種方式,必須在class中加上欲使用class的指標,然後去把他new出來,接著在適當的地方加上delete。

第二種方式使用singleton的做法,只需要在class中include對應的.h檔、然後呼叫GetInstance()即可開始使用,與第一種比較起來,少掉了在class中加上成員變數的麻煩,當然一樣要記住呼叫Release(),才不會造成memory leak。

而所謂的全域問題,問題應該歸咎於使用者的使用不當,比如說並未如上述所說去呼叫Release(),讓他在該消失的時候消失,結果造成該class一直都存在,甚至在程式結束時造成memory leak。那麼用第一種new的方式呢?還是要使用者手動去new以及delete,那麼如果使用者使用不當,不也是會造成memory leak?

當使用者確認在同一時間內(某個時段內),只會有一個實體存在的時候,使用singleton是沒有問題的,這也是singleton最大的存在意義。所以我是覺得這並不是設計原則的問題,只是寫法上的問題,應該沒有所謂的牴觸了OO法則這種情事。

 

 

posted on 2008-10-29 17:59  LancetChang  阅读(132)  评论(0)    收藏  举报

导航