我终于忍受了依赖注射(早就应该);我开始玩Unity并遇到战略模式的问题。我可以使用容器向我返回基于名称的策略的特定实现,但我没有看到我应该如何在上下文中获得正确的策略。
让我们举一个简单的例子说明:上下文是一辆汽车,它有一个IEngine(策略),有2个实现,FastEngine和SlowEngine。代码将沿着这些方向看:
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 ???);
我可以使用容器吗?或者我应该写一个使用容器的工厂?任何指导都将不胜感激 - 我不确定我是否正确思考这个问题!
答案 0 :(得分:27)
DI中的一个常见模式是在运行时,它只会是给定抽象的单个实现。这只会让生活变得更加容易,因为你不需要处理你所描述的模糊性。
但是,有时候,您需要根据上下文改变实现,例如您提供的示例。许多DI容器提供了可以提供限定参数的方法,但这意味着您最终会将代码紧密耦合到特定的DI容器。
更好的解决方案是引入可以提供所需内容的Abstract Factory。像
这样的东西public interface ICarFactory
{
Car Create(IEngine engine);
}
如果您需要注入更多策略,那么Builder设计模式可能更适合。
在任何情况下,重点是不是在容器中注册很多不同的汽车,而是注册一个ICarFactory实现。
在您的客户端代码中,您将使用注入的ICarFactory基于特定的IEngine创建Car实例。
var car = factory.Create(engine);