【发布时间】:2011-01-07 08:42:39
【问题描述】:
这个问题是 Jeffery Palermo 关于如何绕过分支代码和依赖注入 http://jeffreypalermo.com/blog/constructor-over-injection-anti-pattern/
的帖子的结果在他的帖子中,Jeffery 有一个类 (public class OrderProcessor : IOrderProcessor),它在构造函数上采用 2 个接口。一个是验证器IOrderValidator 和IOrderShipper 接口。他的方法代码在只使用IOrderValidator 接口上的方法后分支,从不使用IOrderShipper 接口上的任何东西。
他建议创建一个工厂,该工厂将调用静态方法来获取接口的委托。他正在重构代码中创建一个新对象,这似乎是不必要的。
我想问题的症结在于我们正在使用 IoC 来构建我们所有的对象,无论它们是否被使用。 如果你用 2 个接口实例化一个对象,并且有代码可以分支到不使用其中一个,你如何处理它?
在这个例子中,我们假设 _validator.Validate(order) 总是返回 false 并且永远不会调用 IOrderShipper.Ship() 方法。
原代码:
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
private readonly IOrderShipper _shipper;
public OrderProcessor(IOrderValidator validator, IOrderShipper shipper)
{
_validator = validator;
_shipper = shipper;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
_shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipper : IOrderShipper
{
public OrderShipper()
{
Thread.Sleep(TimeSpan.FromMilliseconds(777));
}
public void Ship(Order order)
{
//ship the order
}
}
重构代码
public class OrderProcessor : IOrderProcessor
{
private readonly IOrderValidator _validator;
public OrderProcessor(IOrderValidator validator)
{
_validator = validator;
}
public SuccessResult Process(Order order)
{
bool isValid = _validator.Validate(order);
if (isValid)
{
IOrderShipper shipper = new OrderShipperFactory().GetDefault();
shipper.Ship(order);
}
return CreateStatus(isValid);
}
private SuccessResult CreateStatus(bool isValid)
{
return isValid ? SuccessResult.Success : SuccessResult.Failed;
}
}
public class OrderShipperFactory
{
public static Func<IOrderShipper> CreationClosure;
public IOrderShipper GetDefault()
{
return CreationClosure(); //executes closure
}
}
这里是在启动时配置这个工厂的方法(用于 ASP.NET 的 global.asax):
private static void ConfigureFactories()
{
OrderShipperFactory.CreationClosure =
() => ObjectFactory.GetInstance<IOrderShipper>();
}
【问题讨论】:
-
大概重构后的代码不应该在构造函数中使用 IOrderShipper ......否则重构的意义何在?
-
在您链接的帖子中,他的重构代码没有在构造函数中使用 IOrderShipper,但在您重构的代码中它确实如此。在这种情况下,我不一定同意 Jeffrey Pallermo,但这是您的实现与他的实现之间的重要区别。
-
猜我复制的代码不正确。我认为把它们都放在这里会更容易=(更正
标签: c# .net dependency-injection inversion-of-control