3

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

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

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();
        }
    }
}
4

5 回答 5

2

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

于 2013-05-15T13:00:14.427 回答
1

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

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

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

于 2014-04-02T05:28:09.507 回答
1

我认为您应该首先意识到 SendIncident 不应该是 IThirdPartyFactory 的一部分。工厂创建对象。SendingIncidents 并非如此。

所以引入一个负责发送Tickets的类:

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 容器,大部分工厂都会为你生成,你只需要定义接口和选择逻辑。

于 2013-05-15T14:55:09.853 回答
1

首先,Marwijn 是正确的,因为您应该有一个单独的 TicketSender 类,该类接受 IThirdPartyFactory 依赖项。

您可以创建一个新界面:

public interface IThirdPartyId
{
    int Id { get; }
}

按照惯例,让您的所有 IThirdParty 实现也实现 IThirdPartyId。然后,您可以按照 Marwijn 的建议将一组 IThirdParty 注入到您的 ThirdPartyFactory 中。工厂可以将它们重铸为 IThirdPartyId 以获取每个的 Id,并使用它来匹配工厂方法的 Id 参数。

这会将您的所有查找逻辑保留在工厂中,而不是在工厂和 IoC 配置之间拆分。

于 2013-05-16T21:24:53.740 回答
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;
        }
    }
}
于 2013-05-15T13:01:04.370 回答