2010-04-09 216 views
10

例子:依賴注入解決循環依賴

class MyClass 
{ 
    Composition m_Composition; 

    void MyClass() 
    { 
     m_Composition = new Composition(this); 
    } 
} 

我很感興趣,這裏使用depenency注射。因此,我將不得不構造重構的東西,如:

void MyClass(Composition composition) 
{ 
    m_Composition = composition; 
} 

但是我現在得到一個問題,因爲Composition -object依靠其剛剛創建MyClass類型的對象。

依賴項容器可以解決這個問題嗎?它應該這樣做嗎?
還是從一開始就只是糟糕的設計?

回答

11

沒有,一個DI容器不會解決循環依賴 - 事實上,它會抗議它通過拋出異常,當您嘗試解決的依賴關係。

在許多DI容器中,您可以提供高級配置,使您可以解決此問題,但是它們本身無法解決循環依賴關係。他們怎麼可能?作爲一個經驗法則,循環依賴是設計氣味

作爲一個經驗法則,循環依賴是設計氣味。如果可以的話,考慮一個替代設計,你可以擺脫循環依賴 - 這也會給你減少耦合。一些可能的替代方案的重新設計:

  • 使用事件信號從一類到另一個。通常情況下,循環依賴已經大部分都朝着一個方向發展,並且在這種情況下,將此信令API的一部分建模爲事件可能會削減該循環。
  • 如果以上情況屬實,但您認爲事件看起來不正確,則可以考慮應用Observer模式。
  • 如果通信必須真正走向雙向,則可以使用組件可以通信的Mediator

不過,我刻意的選擇了字氣味超過反模式,因爲有其他的情況(特別是當你處理外部定義的API),其中無法避免循環依賴。

在這種情況下,您需要決定稍微放鬆依賴關係創建的位置。一旦你知道了,注入一個Abstract Factory可能會有助於延遲其中一個創建,直到創建了該圓的其他部分。

這個other answer是我目前知道的最好的,可用的例子,但如果我可能如此大膽,我即將出版的書也將包含一個解決這個問題的部分。

+0

感謝您的回答。我會試着找出在我的情況下是否可以避免循環引用,雖然我不確定,但是:我需要引用來訂閱Composition的構造函數中的MyClass的一些事件...感謝您提及您的書,它聽起來很有趣。我期待着閱讀它。 – tanascius 2010-04-14 11:16:39

+0

要清楚:儘管您已經可以購買該書的早期訪問權限,但關於處理循環引用的部分尚不可用。 – 2010-04-14 11:54:18