如何用依赖注入取代工厂模式

本文关键字:工厂 模式 取代 注入 何用 依赖 | 更新日期: 2023-09-27 18:13:35

我有以下情况:必须根据每个对象的特定属性(该属性定义为Enum)将对象集合发送给不同的第三方。我打算使用如下所示的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();
        }
    }
}

如何用依赖注入取代工厂模式

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

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

那么引入一个负责发送ticket的类:

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

并使用下面的factory:

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

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

你可以创建一个新的接口:

public interface IThirdPartyId
{
    int Id { get; }
}

按照约定,让所有的IThirdParty实现也实现IThirdPartyId。然后你可以像Marwijn建议的那样将IThirdParty的集合注入到你的ThirdPartyFactory中。工厂可以将它们重新转换为IThirdPartyId来获得每个Id,并使用它来匹配工厂方法上的Id参数。

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

据我所知,这个问题是关于运行时选择或几个候选策略之一的映射-在本例中,根据ThirdParty enum值选择正确的IThirdParty实现。

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

  • 使用元数据角色提示
  • 使用角色接口角色提示
  • 使用部分类型名角色提示

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

为什么不呢?只要稍微调整一下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;
        }
    }
}