如何用依赖注入替换工厂模式

时间:2013-05-15 12:55:58

标签: c# .net dependency-injection factory-pattern

我有以下情况:必须根据每个对象的特定属性将对象集合发送给不同的第三方(该属性定义为枚举)。我打算使用如下的Factory模式实现它。

这可以重构为使用依赖注入吗?

public class ServiceA: IThirdParty
{
    public void Send(Ticket objectToBeSent)
    {
        // a call to the third party is made to send the ticket
    }
}

public class ServiceB: IThirdParty
{
    public void Send(Ticket objectToBeSent)
    {
        // a call to the third party is made to send the ticket
    }
}

public interface IThirdParty
{
    void Send(Ticket objectToBeSent);
}

public static class ThirdPartyFactory
{
    public static void SendIncident(Ticket objectToBeSent)
    {
        IThirdParty thirdPartyService = GetThirdPartyService(objectToBeSent.ThirdPartyId);
        thirdPartyService.Send(objectToBeSent);
    }

    private static IThirdParty GetThirdPartyService(ThirdParty thirdParty)
    {
        switch (thirdParty)
        {
            case ThirdParty.AAA:
                return new ServiceA();

            default:
                return new ServiceB();
        }
    }
}

5 个答案:

答案 0 :(得分:2)

是的,可以重构 - 将服务注入SendIncident或其类。

答案 1 :(得分:1)

我认为你应该首先意识到SendIncident不应该是IThirdPartyFactory的一部分。工厂创造对象。 SendingIncidents不是那样的。

所以介绍一个负责发送票证的类:

public TicketSender
{
    IThirdPartyFactory _factory

    public void TicketSender(IThirdPartyFactory factory)
    {
        _factory = factory;
    }


    public void SendIncident(Ticket ObjectToBeSent)
    {
         var service = _factory.GetThirdPartyService(ObjectToBeSent.ThirdPartyId);
         service.SendIncident(ObjectToBeSent);
    }
}

使用以下工厂:

public class ThirdPartyFactory : IThirdPartyFactory
{
    IThirdParty serviceA;
    IThirdParty serviceB;

    public ThirdPartyFactory(IThirdParty serviceA, IThirdParty serviceB)
    {
        _serviceA = serviceA;
        _serviceB = serviceB;
    }

    public IThirdParty GetThirdPartyService(ThirdParty thirdParty)
    {
        switch (thirdParty)
        {
            case ThirdParty.AAA:
                return serviceA;

            default:
                return serviceB;
        }
    }
}

如果您正在使用像Windsor这样的IOC容器,那么将为您生成大部分工厂,并且您只需定义接口和选择逻辑。

答案 2 :(得分:1)

首先,Marwijn是正确的,你应该有一个单独的TicketSender类,它接受IThirdPartyFactory依赖。

您可以创建一个新界面:

public interface IThirdPartyId
{
    int Id { get; }
}

按照惯例,让所有IThirdParty实现都实现IThirdPartyId。然后你可以像Marwijn建议的那样将一系列IThirdParty注入你的ThirdPartyFactory。工厂可以将它们重新设置为IThirdPartyId以获取每个的Id,并使用它来匹配工厂方法上的Id参数。

这样可以将所有查找逻辑保留在工厂中,而不是在工厂和IoC配置之间进行拆分。

答案 3 :(得分:0)

为什么不呢?只需稍微调整ThirdPartyFactory即可成为抽象工厂,不要使用静态。

public class ThirdPartyFactory : IThirdPartyFactory
{
    public ThirdPartyFactory(IThirdParty serviceA, IThirdParty serviceB)
    {
        this.serviceA = serviceA;
        this.serviceB = serviceB;
    }
    IThirdParty serviceA;
    IThirdParty serviceB;

    public void SendIncident(Ticket objectToBeSent)
    {
        IThirdParty thirdPartyService = GetThirdPartyService(objectToBeSent.ThirdPartyId);
        thirdPartyService.SendIncident(objectToBeSent);
    }

    private IThirdParty GetThirdPartyService(ThirdParty thirdParty)
    {
        switch (thirdParty)
        {
            case ThirdParty.AAA:
                return serviceA;

            default:
                return serviceB;
        }
    }
}

答案 4 :(得分:0)

据我所知,这个问题是关于运行时选择或几个候选策略之一的映射 - 在这种情况下,根据IThirdParty枚举值选择正确的ThirdParty实现。

至少有三种方法可以做到这一点,而且它们都不需要工厂:

我个人偏好是部分类型名称角色提示。