依賴倒置原則通過確保代碼依賴於抽象而不是具體實現來解耦代碼。依賴註入(Dependency Injection,DI)模式是依賴倒置原則的一種實現方式,DI提供服務所需的所有類,常見的DI三種方式:構造註入、屬性註入和方法註入。 依賴倒置原則的使用意圖: 高層模塊不應該依賴於低層模塊。兩者都應該依賴 ...
依賴倒置原則通過確保代碼依賴於抽象而不是具體實現來解耦代碼。依賴註入(Dependency Injection,DI)模式是依賴倒置原則的一種實現方式,DI提供服務所需的所有類,常見的DI三種方式:構造註入、屬性註入和方法註入。
依賴倒置原則的使用意圖:
高層模塊不應該依賴於低層模塊。兩者都應該依賴於抽象。
抽象不應該依賴於細節。具體細節應該依賴於抽象
代碼示例
Bad Code
/// <summary>
/// 聖誕節商品折扣類
/// </summary>
public class ChristmasProductDiscount
{
public ChristmasProductDiscount()
{
}
}
/// <summary>
/// 一個商品類,用於演示和ChristmasProductDiscount類的交互
/// </summary>
public class Product
{
public void AdjustPriceWith(ChristmasProductDiscount dicount) { }
}
/// <summary>
/// 模擬一個簡單的產品數據倉庫
/// </summary>
public class LinqProductRepository
{
public IEnumerable<Product> FindAll() {
return new List<Product>();
}
}
/// <summary>
/// 產品服務類
/// </summary>
public class ProductService
{
private LinqProductRepository _productRepository;
private ChristmasProductDiscount _discountStrategy;
public ProductService()
{
_productRepository = new LinqProductRepository();
_discountStrategy = new ChristmasProductDiscount();
}
public IEnumerable<Product> GetProducts() {
IEnumerable<Product> products = _productRepository.FindAll();
foreach (var p in products)
{
p.AdjustPriceWith(_discountStrategy);
}
return products;
}
}
上面的代碼中,ProductService類緊密的與LinqProductRepository和ChristmasProductDiscount耦合在了一起。一旦LinqProductRepository或ChristmasProductDiscount類無效,將影響ProductService類的使用。為了將高層模塊(ProductService)與低層模塊(LinqProductRepository和ChristmasProductDiscount)解耦,可以通過DI的方式來重構代碼。
/// <summary>
/// 產品折扣策略介面
/// </summary>
public interface IProductDiscountStrategy
{
}
/// <summary>
/// 聖誕節商品折扣類
/// </summary>
public class ChristmasProductDiscount:IProductDiscountStrategy
{
public ChristmasProductDiscount()
{
}
}
/// <summary>
/// 一個商品類,用於演示和ChristmasProductDiscount類的交互
/// </summary>
public class Product
{
/// <summary>
/// 引用介面而不是具體的策略
/// </summary>
public void AdjustPriceWith(IProductDiscountStrategy dicount) { }
}
/// <summary>
/// 為LinqProductRepository類引入介面
/// </summary>
public interface IProductRepository
{
IEnumerable<Product> FindAll();
}
/// <summary>
/// 模擬一個簡單的產品數據倉庫
/// </summary>
public class LinqProductRepository:IProductRepository
{
public IEnumerable<Product> FindAll() {
return new List<Product>();
}
}
/// <summary>
/// 產品服務類
/// </summary>
public class ProductService
{
private IProductRepository _productRepository;
/// <summary>
/// 通過構造器註入方式,將低層類的創建指責外拋出去
/// </summary>
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
/// <summary>
/// 通過方法註入的方式將折扣類的實例化外移
/// </summary>
public IEnumerable<Product> GetProductsAndApplyDiscount(IProductDiscountStrategy discountStrategy) {
IEnumerable<Product> products = _productRepository.FindAll();
foreach (var p in products)
{
p.AdjustPriceWith(discountStrategy);
}
return products;
}
}