使用Unity的策略模式和依赖注入 [英] Strategy Pattern and Dependency Injection using Unity

查看:157
本文介绍了使用Unity的策略模式和依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于得到我的脚湿润依赖注射(早期);我开始玩Unity,遇到战略模式的问题。我可以使用容器返回给我基于名称的策略的具体实现,但是我看不到我应该如何在上下文中获得正确的策略。

我们来说明一个简单的例子:上下文是一个车,其中有一个IEngine(策略),有2个实现,FastEngine和SlowEngine。代码将如下所示:

  public interface IEngine 
{
double MaxSpeed
{
get;
}
}

内部类FastEngine:IEngine
{
public double MaxSpeed
{
get
{
返回100d;
}
}
}

内部类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容器= 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>(使用Fast或Slow ??? ; 

我可以使用容器做这个吗?还是应该写一个使用容器的工厂?任何的指导都不会感激 - 我不知道我在想这个事情!

解决方案

DI的一个常见模式是, em>在运行时只需要一个给定抽象的一个实现,这只会使生活变得容易一些,因为你不需要处理诸如你所描述的歧义。



但是,有时您需要根据上下文来更改实现,例如您给出的示例。许多DI容器提供了可以提供限定参数的方法,但是这意味着你会结束紧密的联运将您的代码转移到特定的DI容器。



一个更好的解决方案是介绍抽象工厂,可以提供您所需要的。像

  public interface ICarFactory 
{
汽车制作(IEngine引擎);
}

如果您需要注入更多的策略,也许 Builder 的设计模式可能更适合。



无论如何,关键在于,不要在容器中注册很多不同的汽车,而是注册一个ICarFactory实现。



在您的客户端代码中,您将使用注入ICarFactory创建一个基于特定IEngine的Car实例。

  var car = factory.Create(engine); 


I am finally getting my feet wet with Dependency Injection (long overdue); I got started playing with Unity and run into an issue with the strategy pattern. I can use the container to return to me specific implementations of a strategy based on a name, but what I don't see is how I am supposed to get the right strategy in the context.
Let's illustrate on a simple example: the context is a car, which has an IEngine (the strategy), with 2 implementations, FastEngine and SlowEngine. The code would look along these lines:

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;
    }
}

My problem is the following: how should I go about instantiating a fast car or a slow car? I can use the container to provide me with each implementation, and I can set a "default" implementation to use:

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);

but what I would like is to be able to request a car with a specific implementation of the strategy - something like

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

Can I use the container to do that? Or should I write a Factory which uses the container? Any guidance would be appreciated - I am not sure I am thinking right about this!

解决方案

A common pattern in DI is that at run-time there's only going to be a single implementation of a given abstraction. That just makes life a whole lot easier, as you don't need to deal with the ambiguity such as the one you describe.

However, sometimes, you need to vary an implementation based on context, such as the example you give. Many DI Containers provide ways where you can provide a qualifying parameter, but that means that you will end up tightly coupling your code to a specific DI Container.

A much better solution would be to introduct an Abstract Factory that can provide what you need. Something like

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

If you need to inject more Strategies, perhaps the Builder design pattern might fit even better.

In any case, the point is that instead of registering a lot of different Cars in the container, you would instead register a single ICarFactory implementation.

In your client code, you would use the injected ICarFactory to create a Car instance based on a particular IEngine.

var car = factory.Create(engine);

这篇关于使用Unity的策略模式和依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆