23

我終於使我的腳溼依賴注入(長期過期);我開始玩Unity,並遇到了一個與戰略模式有關的問題。我可以使用容器向我返回基於名稱的策略的特定實現,但我沒有看到的是我如何在上下文中獲得正確的策略。
讓我們舉個簡單的例子來說明:上下文是一輛汽車,它有一個IEngine(策略),有2個實現,FastEngine和SlowEngine。該代碼將沿着這些路線看:使用Unity的策略模式和依賴注入

public interface IEngine 
{ 
    double MaxSpeed 
    { 
     get; 
    } 
} 

internal class FastEngine:IEngine 
{ 
    public double MaxSpeed 
    { 
     get 
     { 
      return 100d; 
     } 
    } 
} 

internal class SlowEngine:IEngine 
{ 
    public double MaxSpeed 
    { 
     get 
     { 
      return 10d; 
     } 
    } 
} 

public class Car 
{ 
    private IEngine engine; 
    public double MaximumSpeed 
    { 
     get 
     { 
      return this.engine.MaxSpeed; 
     } 
    } 

    public Car(IEngine engine) 
    { 
     this.engine = engine; 
    } 
} 

我的問題是:我應該如何去實例化一個速度快的汽車或慢車?我可以使用的容器爲我提供每個實現,我可以設置一個「默認」的方案中使用:

IUnityContainer container = new UnityContainer(); 
container.RegisterType<IEngine, FastEngine>(); 
container.RegisterType<IEngine, FastEngine>("Fast"); 
container.RegisterType<IEngine, SlowEngine>("Slow"); 
var car = container.Resolve<Car>(); 
Assert.AreEqual(100, car.MaximumSpeed); 

但我想是能夠請求車與具體實現的策略 - 類似於

var car = container.Resolve<Car>(??? use "Fast" or "Slow ???); 

我可以使用容器來做到這一點嗎?或者我應該寫一個使用容器的工廠?任何指導將不勝感激 - 我不知道我在想這個!

回答

26

DI中的一個常見模式是在運行時這裏只會有一個給定抽象的實現。這隻會讓生活變得更容易,因爲你不需要處理模糊的問題,比如你所描述的那個。

但是,有時候,您需要根據上下文來改變實現,例如您給出的示例。許多DI容器提供了可以提供限定參數的方式,但這意味着您最終會將代碼緊密耦合到特定的DI容器。

更好的解決方案是引入Abstract Factory,可以提供您所需要的。像

public interface ICarFactory 
{ 
    Car Create(IEngine engine); 
} 

如果需要注入更多的戰略東西,也許是Builder設計模式可能適合,甚至更好。

無論如何,重點不在於在容器中註冊很多不同的Cars,而是註冊一個ICarFactory實現。

在您的客戶端代碼中,您將使用注入的ICarFactory創建基於特定IEngine的Car實例。

var car = factory.Create(engine); 
+0

謝謝,有見地的答案。我使用戰略模式,在運行時多種策略交換,很多;默認情況下,我會做你所描述的(工廠或生成器),但我看到很多策略模式和DI關聯,雖然這可能有所幫助。從你所說的話來看,一個容器似乎只有一點幫助。 – Mathias 2009-11-10 20:43:14

+0

我仍然認爲集裝箱是非常有幫助的。在這些情況下,他們只會注入工廠而不是策略,但我想你仍然可以選擇使用容器來實現工廠... – 2009-11-10 21:02:15

+4

哦,我想我明白你的意思了;而不是退回合適的車輛,根據發動機返回正確的工廠。在任何情況下,您的評論re:用於爲抽象提供單個實現的容器都非常有用;它與我看到的以配置爲導向的示例一致。在該框架中,您可以擁有策略模式,但特定的部署只會配置一個實施。 – Mathias 2009-11-11 06:14:11