2012-04-04 75 views
7

免責聲明:我喜歡這個 項目中使用dependency injection,並有全線鬆耦合基於接口的設計,但使用依賴注入已經在這個項目中被擊落。另外SOLID設計原則(和一般design patterns)是我工作的外國事物,我自己對他們中的許多人都是新手。因此,在爲此問題提出更好的設計時,請考慮 。有更好的設計選擇嗎?

下面是我正在處理的代碼的簡化版本,因此它可能看起來有點麻煩。如果是的話,我表示歉意。考慮下面的類:

// Foo is a class that wraps underlying functionality from another 
// assembly to create a simplified API. Think of this as a service layer class, 
// a facade-like wrapper. It contains a helper class that is specific to 
// foo. Other AbstractFoo implementations have their own helpers. 

public class Foo : AbstractFoo 
{ 
    private readonly DefaultHelper helper; 
    public override DefaultHelper Helper { get { return helper; } } 

    public Foo() 
    { 
     helper = new Helper("custom stuff"); 
    } 

    public override void Operation1(string value) 
    { 
     Console.WriteLine("Operation1 using " + value); 
    } 

    public override void Operation2() 
    { 
     Console.WriteLine("Operation2"); 
    } 
} 

// Helper derives from a default implementation and allows us to 
// override it's methods to do things specific for the class that 
// holds this helper. Sometimes we use a custom helper, sometimes 
// we use the default one. 

public class Helper : DefaultHelper 
{ 
    private readonly string customStuff; 

    public Helper(string value) 
    { 
     customStuff = value; 
    } 

    public override void DoSomethingHelpful() 
    { 
     Console.WriteLine("I was helpful using " + customStuff); 
    } 
} 

說這兩個類的使用方法如下:

// foo referenced and used in one part of code 
    var foo = new Foo(); 
    foo.Operation2(); // or foo.Operation1(); 

    // some other point in the program where we don't have a reference to foo 
    // but do have a reference to the helper 
    helper.DoSomethingHelpful(); 

但是我現在發現,我還需要執行foo.Operation1在一些實現helper.DoSomethingHelpful();?潛在的解決方法我想到的將是:

  1. 有foo和助手有雙向關係。因此,在DoSomethingHelpful我們可以稱之爲foo.Operation2
  2. 有富實現IHelp界面和移動「幫手」的代碼到富
  3. 使用授權,並通過該方法操作2爲Action<string>委派到助手的構造函數。

這些方法都沒有似乎是理想的(雖然我非常確定我不喜歡選項1和很擔心可維護性與選項3如果我們發現以後,我們需要通過在更多的代表)。這讓我想知道Helper/Foo組合的初始設計是否有問題。思考?

+0

我想你的意思是'DefaultHelper'而不是'DefualtHelper'。 – ja72 2012-04-04 14:35:15

+0

@ ja72,拼寫從來不是我的強項,我更新了這個錯字。 – Matt 2012-04-04 14:37:46

+1

+1免責聲明...有一個偉大的笑聲。 – scottheckel 2012-04-04 14:39:57

回答

1

「這些方法似乎都不是理想的(雖然我已經差不多 確定我不喜歡選項1,很擔心可維護性 與選項3,如果我們發現以後,我們需要通過在更多代表) 這讓我想知道Helper/Foo組合的初始設計 是否有問題。「

你完全正確 - Helper和Foo的設計存在問題。您最初描述的基本Foo/Helper關係很好,並且當您必須包裝其他不受控制的對象時,它是常見模式。但你說:

「如果我發現,我還需要在helper.DoSomethingHelpful()的一些 實現執行foo.Operation1;」?

這是我們遇到問題的地方。你開始描述Foo依賴於Helper的關係;現在你正在描述一個Helper依賴於Foo的關係。這立即告訴我你的依賴關係糾結了。對象之間的依賴關係應該只有一種方式;事實上依賴注入依賴於此。

+0

+1我同意這裏,並感謝您確定爲什麼我不喜歡選項1和3(即糾結的依賴關係)。爲什麼我認爲在這種情況下將Foo和Helper的功能相結合是有意義的,因爲它們相互依賴。使用IHelp接口,我仍然可以將Foo視爲它是代碼中其他位置的Helper。 – Matt 2012-04-05 16:58:23

1

我想你有你需要的東西。儘量不要設計「以防萬一我以後需要它」,並且不要修復沒有損壞的東西。如果將來您需要從助手中使用Operation1,然後將其作爲依賴於構造函數(如您所建議的那樣),或者將其傳遞給您正在調用的方法。這將取決於場景,並且當你真正需要某些東西時你就會擁有它。

編輯:改變了「試圖不爲未來設計」,因爲它似乎並不是我想說的。在這個問題

再次編輯,由於變化

你可以使這樣的事情:

helper.DoSomethingUsefulWith(foo); 

所以你的輔助方法,將收到的訂單需要依賴工作

+0

儘量不要爲未來設計?我明白你想說什麼,但總的來說,我不認爲這是很好的建議。 – 2012-04-04 14:51:48

+0

設計它可以保持和擴展:是的!添加功能以防萬一以後需要:不!這就是我想說的:)。我想我沒有爲它選擇最好的單詞嘿嘿 – ivowiblo 2012-04-04 14:53:59

+0

@ivowiblo,我更新了我的問題,因爲它不是一個真正的「假設」情況。這是我現在遇到的要求。我應該更清楚。抱歉。 – Matt 2012-04-04 15:15:30

3

如何關於休閒(「使用」)關係:

public class Helper : DefaultHelper 
{ 
    private readonly string customStuff; 

    public Helper(string value) 
    { 
     customStuff = value; 
    } 

    public override void DoSomethingHelpful(AbstractFoo foo) 
    { 
     foo.Operation1(); 
     Console.WriteLine("I was helpful using " + customStuff);   
    } 
} 

因此,您修改抽象幫助程序以期望引用正確的Foo實現。

+1

在UML中,這是[依賴項](http://publib.boulder.ibm.com/infocenter/rtnlhelp/v6r0m0/index.jsp?topic=%2Fcom.ibm.xtools.modeler.doc%2Ftopics%2Fcdepend。 html)或「使用」關係 – SwDevMan81 2012-04-04 15:01:18

+0

這個問題與Helper具有相同的由AbstractFoo和其他類使用的簽名(即AbstractBoo)。如果我將基類更改爲接受foo,那麼當我使用boo中的helper時,這沒有幫助,如果這樣做合理的話。可能需要傳入Boo(或者可能沒有參數)。 – Matt 2012-04-04 15:58:45

+0

@Matt:那麼你想讓'BooHelper'能夠像'FooHelper'獲得'Foo'一樣使用'Boo'嗎?你的評論讓我很困惑。 – ja72 2012-04-04 18:21:55

1

我認爲你所有的解決方案都很好;他們只是提供不同的功能。這些差異現在並不重要,但可能在未來。

你更喜歡第二個,你的直覺是這裏最好的指南,你比我們其他人更瞭解你的代碼的未來。我喜歡你的第二個解決方案,因爲它擺脫了課堂,而且更簡單。由於它的簡單性,如果你以後需要做其他事情,你不必扔掉很多工作。

第一種方法可讓您用不同的Helper(IHelper?)實例和子類玩遊戲。最後一種方法爲Helper增加了很多靈活性。 (雖然它可能會增加很多,但不需要助手,只需要傳遞給它的方法。)如果要麼解決更多未來未被發現的問題,可以稍後切換到使用它們。

+0

+1我同意接口的方法,結合Foo和Helper可能是三者中較好的一個,也是我決定採用的方法之一。 – Matt 2012-04-05 16:59:55