2013-01-13 58 views
2

我想了解爲什麼單身人士會皺起眉頭。試圖找出爲什麼單身人士被認爲是壞事;爲什麼聚合更好?

比方說,我有單MyClass的:

class MyClass 
{ 
public: 
    void doSomething(); 
    static MyClass* getInstance(); 
private: 
    int whatever; 
    static MyClass* myClass; 
    MyClass(); 
}; 

我有一個類引用它:

void A::B() 
{ 
    ... 
    MyClass::getInstance()->doSomething(); 
} 

我讀過的是,現在的A類是依賴於MyClass的。測試類A有效地意味着同時測試MyClass。任何地方的任何人都可以同時修改我們的MyClass,所以A :: B()的結果是不可預知的。

但爲什麼全球可訪問性是這個原因呢?如果我們有聚合,會怎麼樣?如果A類有一個指向我們的MyClass對象的指針或引用,而其他類也有指向同一對象的指針或引用呢?

class A 
{ 
public: 
    void B(); 
private: 
    MyClass* myClass; 
}; 
void A::B() 
{ 
    ... 
    myClass->doSomething(); 
} 

你不能有同樣的問題,因此一些其它類的同時修改同一MyClass的對象,因此,A :: B()是依賴於?我想問題是,是不是像「全球狀態」一樣在多個地點提及同一事物?

(我承認這個問題已經被公佈,但我不認爲任何人有特別要求,爲什麼同一個對象的多個引用是沒有更好的。)

回答

1

「任何人在任何地方可以修改我們MyClass在同一時間「

這隻能在某種多線程或多進程環境中。如果這是你的擔憂,你的第二個例子似乎不會更好。

因爲可能的併發訪問,所以不建議在多線程環境中使用全局函數或單例函數,這就是您正在談論的內容。爲了避免併發性問題,您需要處理同步機制 - 並不總是那麼容易。

即使沒有多線程,Globals也傾向於使代碼難以在任何不重要的系統中進行管理,調試和控制。

通常「聚合」不是「單身」的替代方案。單例的替代方案是多個實例,每個實例專用於特定的線程,或者本地特定的類或方法 - 可能是您的「聚合」意味着什麼 - 從而避免了併發和控制/代碼管理問題。

聚合「委派」「對象組合物」(或多或少同義在此上下文中術語)通常被認爲是替代繼承:而不是從基類繼承的功能性,通常更希望設計一個完全獨立的類來執行必要的功能,並由調用類 - 「黑匣子」概念引用和控制。

繼承問題之一是它傾向於強制派生類來處理派生類中可能不合適的基類的實現和行爲。它總是強制將實現細節暴露給派生類,從而違反封裝。理想情況下,設計良好的類層次結構可以避免這個問題,但是如果您要處理類Cat(動物),類Dog(動物)等的教科書定義之外的任何內容,設計這樣的類層次通常不是一件簡單的事情。

+0

「在多線程環境中不建議使用單身...」。如果你的單例只是用來讀取一個配置文件,並且它的狀態與所有線程的啓動完全相同(或者來自任何和所有客戶端的web請求,例如應用程序名稱)。我不是這方面的專家,只是對這種情況感到好奇。 –

+0

@ bob-the-destroyer - 假設文件系統被配置爲允許併發讀取(以及只讀),讀取靜態文件應該不成問題。 – Vector

+0

@Mikey - 我認爲當我使用「聚合」這個詞時,我的意思是它與「遏制」形成鮮明對比。我在想象一個引用單個對象的多個對象的場景。看起來像多個對象可以引用單個對象時,您可能會遇到許多「全局可訪問性」的危險。雖然,在這種情況下,我想你至少已經授予了這些對象的引用副本,這是一種說「我信任你」的方式,而不是任何人都可以修改的全局可訪問性。 – vmayer

相關問題