我正在開發一個側面項目,以便更好地理解控制和依賴注入的反轉以及不同的設計模式。在依賴注入中使用策略和工廠模式
我想知道是否有使用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