2011-03-22 14 views
2

我有一個上下文對象有幾個有用的屬性和方法。其他對象在構造函數中接受這個上下文對象。但是,上下文對象可以將這些其他對象作爲公共屬性。請看下圖:對象A具有對象B的引用,該對象具有對象A作爲公共屬性 - 不良設計?

public class Foo { 
    private IContext Context { get; private set; } 

    public Foo(IContext context) { 
     Context = context; 
    } 
} 

public class SomeContext : IContext { 
    public Foo SomeProperty { get; set; } 
    /* 
     Other useful properties and methods as defined in IContext 
    */ 

    public SomeContext() { 
     SomeProperty = new Foo(this); 
    } 
} 

現在我可以做一些有用的方法上富:

public void FooIt() { 
    IUseful bar = this.Context.GetUsefulInterface(); 
    bar.DoUsefulThing(); 
} 

但是,它可能會導致一些非常奇怪的東西。考慮Foo上的這些方法:

public void DoSomething() { 
    /* useful stuff */ 
} 

public void DoSomethingElse() { 
    this.Context.SomeProperty.DoSomething(); // could just call this.DoSomething(); 
    this.Context.SomeProperty.DoSomethingElse(); // stack overflow! 
} 

這是否被認爲是糟糕的設計/代碼氣味?背景對象的原因有些涉及,我想更多地將問題提到循環參考。如果認爲不好,有什麼方法打破這種週期性關係?

回答

2

如果沒有領域知識,當試圖設計出循環依賴時很難知道從哪裏開始,所以我只想概括一下。

當您沒有表達層次關係時,循環引用很糟糕,在這種關係中,返回父級是需要或有用的。這是因爲它促進了循環中類型之間的強耦合,難以正確構造/刪除,並且在遍歷時容易出現錯誤。

但是,如果您有層次關係,並且需要/有用來遍歷層次結構,則具有循環引用是非常有意義的。

你可能想要避免的一件事是一次試圖調用太深入你的屬性。這會增加你的耦合度,並且很容易導致你發現的堆棧溢出異常等錯誤。

// Reaches too far. Makes this depend on the interface of SomeProperty 
this.Context.SomeProperty.DoSomething(); 

// ... 

// Not reaching too far. Only depends on Context. 
// This might forward to SomeProperty.DoSomething() 
this.Context.DoSomething(); 

根據你如何修復它,這也可能幫助你打破堆棧溢出。

請參見:http://en.wikipedia.org/wiki/Law_of_Demeter

2

不錯,但絕對不理想。我認爲這是你不應該在構造函數中創建一個上下文對象,上下文對象需要創建對象。上下文應該是您正在創建的對象的外部事物。

但是,使用您的上下文對象創建「無限循環」排序沒有問題。 ASP.NET MVC ControllerContext在某些方面做了非常類似的事情;你只是通常不把它像這樣:

ControllerContext.Controller.ControllerContext.Controller // etc 
0

循環關係是壞在非託管環境,因爲你需要一個弱引用打破循環的關係(或否則你會不可避免地泄漏參與週期的對象) 。儘管如此,我無法想到在受管理的環境中將它們標記爲「壞」的具體原因。

事實上,有充足的理由有循環引用。例如,在UI樹中,父級用戶界面元素知道他們的孩子,孩子也知道他們的父母。

-1

通常情況下,循環引用是壞設計的氣味。然而,有幾種情況,哪裏是循環引用的好方法(在Winforms中:Control.Controls與Control.Parent)。

如果你有循環引用,你應該檢查正確的值。如果您有父母與子女的關係,並且將子女從父母中移除,則孩子不應該參考父母,父母不應該參考子女。

+0

爲什麼循環引用通常一個代碼味道? – zneak 2011-03-22 18:36:42

+0

因爲如果循環引用比「單向」引用更難維護。我經常見到使用循環引用的buggy實現,並在另一個模式以相同效率解決問題的場景中使用。 – TcKs 2011-03-23 10:47:30

相關問題