2011-06-10 35 views
0

我有類,如下面問題上類相互作用

class A 
{ 
private: 
    B b; 
} 

class B 
{ 
private: 
    C c; 
    D d; 

} 

C和d是存儲類主要包含結構和數據結構。 B將它們包裝在一起。我想知道如果我有一個對象A,獲取數據C和D或者執行一個函數的更好方法是什麼?

For example: 
class A 
{ 
private: 
    B b; 
public: 
    B* GetB() { return &b;} 
}; 

class B 
{ 
private: 
    C c; 
    D d; 
public: 
    C* GetC() {return &c;} 
    D* GetD() {return &d;} 
}; 

class C 
{ 
public: 
    functionA(); 
}; 


A a; 
B* b = a.GetB(); 
C* c = b->GetC(); 
c->functionA(); 

OR

我不應該暴露在所有對象B:

class A 
{ 
private: 
    B b; 
public: 
    C* GetC() { return &b.GetC();} 
    D* GetD() { return &b.GetD();} 
}; 

A a; 
C* c = a.GetC(); 
c->functionA(); 

OR

我不應該暴露對象B,C和d

class A 
{ 
private: 
    B b; 
public: 
    void performFunctionA() { b.performFunctionA(); } 
}; 

class B 
{ 
private: 
    C c; 
    D d; 
public: 
    void performFunctionA() { c.functionA();} 
}; 

class C 
{ 
public: 
    functionA(); 
}; 


A a; 
a.performFunctionA(); 

爲什麼我們選擇一個諾特爾?

謝謝

回答

1

良好的封裝說,你應該公開儘可能少的實現細節。在你的情況下,這意味着贊成你的最後一個選項,而不是暴露B,CD。這樣,對B,CD的任何更改都可以與A的用戶隔離。

+0

感謝您的答覆。如果我使用最後一個選項,如果c有10個函數,並且我需要訪問它們,那麼在類B和類A中,我需要在這兩個類中添加10個接口。這不是一點點重複嗎? – leslieg 2011-06-10 03:13:37

1

我最喜歡你最後的選擇。從用戶的角度考慮一些事情。當有人使用A對象時,如果他們必須知道的是他們想要performFunctionA,那麼最容易。他們不需要知道或關心一個A包含一個包含C和D的B.另外,如果您更改了B的內部細節,則類A的用戶將不必重新編譯。

如果您確實選擇將句柄暴露給內部對象(如在其他示例中那樣),請考慮在實際情況下通過指向const或引用const來返回它們。這可以幫助最大限度地降低用戶意外修改違反其中一個類的不變量的風險。

+0

感謝您的回覆。如果我使用最後一個選項,如果c有10個函數,並且我需要訪問它們,那麼在類B和類A中,我需要在這兩個類中添加10個接口。這不是一點點重複嗎? – leslieg 2011-06-10 03:13:25

+0

@leslieg,是的。你可能會問,爲什麼C被埋在兩個不同的類中,如果它提供了這樣一個關鍵的接口。但是你經常處理遺留代碼,你別無選擇。就我個人而言,我寧願在我的文本編輯器的複製和粘貼功能上得到一些好的做法,而不是盲目暴露內部成員數據。後一種選擇可能更容易導致維護問題。 – 2011-06-10 11:09:31

0

Law of Demeter

  • 各單位應只限於對其他單位 知識:只有 單位「密切」與當前 單元。

  • 每個單位只能與其 朋友交談;不要與陌生人交談。

  • 只與您的直接朋友交談。

最後一個選項似乎遵守這個法律,在我看來是最好的。

關於你的公開內部類的維基也說

德米特 法的缺點是它有時需要寫 大量的小「包裝」 的其他方法問題方法將方法調用傳播到組件。

所以最後它是你的電話。如果你需要暴露幾種方法,我認爲適合德米特法。它提供了很好的指導。另一方面,如果你認爲你的代碼變得笨重,那麼它可能是一種代碼味道:-)