如何用依赖注入取代工厂模式
本文关键字:工厂 模式 取代 注入 何用 依赖 | 更新日期: 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;
}
}
}