我正在开发一个侧面项目,以便更好地理解控制和依赖注入的反转以及不同的设计模式。在依赖注入中使用策略和工厂模式
我想知道是否有使用DI的工厂和战略模式的最佳实践?
我的挑战来自何时一个策略(由工厂构建)需要不同的参数为每个可能的构造函数和实现。因此,我发现自己在服务入口点声明所有可能的接口,并通过应用程序传递它们。因此,必须为新的和各种策略类实现更改入口点。
为了下面的说明,我已经组合了一个配对的例子。我的这个项目的堆栈是.NET 4.5/C#和Unity for IoC/DI。
在本示例应用程序中,我添加了一个默认的程序类,负责接受虚构的订单,并根据订单属性和所选的运输供应商计算运输成本。对于UPS,DHL和Fedex有不同的计算方法,并且每个实现可能会或可能不会依赖额外的服务(打击数据库,api等)。
public class Order
{
public string ShippingMethod { get; set; }
public int OrderTotal { get; set; }
public int OrderWeight { get; set; }
public int OrderZipCode { get; set; }
}
虚拟程序或服务来计算运费成本
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategyFactory _shippingStrategyFactory;
public Program(IShippingStrategyFactory shippingStrategyFactory)
{
_shippingStrategyFactory = shippingStrategyFactory;
}
public int DoTheWork(Order order)
{
// assign properties just as an example
order.ShippingMethod = "Fedex";
order.OrderTotal = 90;
order.OrderWeight = 12;
order.OrderZipCode = 98109;
IShippingStrategy shippingStrategy = _shippingStrategyFactory.GetShippingStrategy(order);
int shippingCost = shippingStrategy.CalculateShippingCost(order);
return shippingCost;
}
}
// Unity DI Setup
public class UnityConfig
{
var container = new UnityContainer();
container.RegisterType<IShippingStrategyFactory, ShippingStrategyFactory>();
// also register IWeightMappingService and IZipCodePriceCalculator with implementations
}
public interface IShippingStrategyFactory
{
IShippingStrategy GetShippingStrategy(Order order);
}
public class ShippingStrategyFactory : IShippingStrategyFactory
{
public IShippingStrategy GetShippingStrategy(Order order)
{
switch (order.ShippingMethod)
{
case "UPS":
return new UPSShippingStrategy();
// The issue is that some strategies require additional parameters for the constructor
// SHould the be resolved at the entry point (the Program class) and passed down?
case "DHL":
return new DHLShippingStrategy();
case "Fedex":
return new FedexShippingStrategy();
default:
throw new NotImplementedException();
}
}
}
现在的策略接口和实现。 UPS是一个简单的计算,而DHL和Fedex可能需要不同的服务(和不同的构造参数)。
public interface IShippingStrategy
{
int CalculateShippingCost(Order order);
}
public class UPSShippingStrategy : IShippingStrategy()
{
public int CalculateShippingCost(Order order)
{
if (order.OrderWeight < 5)
return 10; // flat rate of $10 for packages under 5 lbs
else
return 20; // flat rate of $20
}
}
public class DHLShippingStrategy : IShippingStrategy()
{
private readonly IWeightMappingService _weightMappingService;
public DHLShippingStrategy(IWeightMappingService weightMappingService)
{
_weightMappingService = weightMappingService;
}
public int CalculateShippingCost(Order order)
{
// some sort of database call needed to lookup pricing table and weight mappings
return _weightMappingService.DeterminePrice(order);
}
}
public class FedexShippingStrategy : IShippingStrategy()
{
private readonly IZipCodePriceCalculator _zipCodePriceCalculator;
public FedexShippingStrategy(IZipCodePriceCalculator zipCodePriceCalculator)
{
_zipCodePriceCalculator = zipCodePriceCalculator;
}
public int CalculateShippingCost(Order order)
{
// some sort of dynamic pricing based on zipcode
// api call to a Fedex service to return dynamic price
return _zipCodePriceService.CacluateShippingCost(order.OrderZipCode);
}
}
上述问题是每个策略都需要额外的不同服务来执行'CalculateShippingCost'方法。这些接口/实现是否需要在入口点(程序类)注册并通过构造函数传递?
是否有其他模式更适合完成上述场景?也许是Unity可以专门处理的事情(https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx)?
我非常感谢任何帮助或在正确的方向微调。
感谢, 安迪
请参见[使用DI和Ioc的工厂方法](http://stackoverflow.com/a/31971691/181087)。 – NightOwl888