本文中DI指依賴倒置。
依賴的概念
Baidu百科:依靠別人或事物而不能自立或自給。
軟體開發中的依賴:依賴描述了兩個模型元素之間的關係,如果被依賴的模型元素髮生變化就會影響到另一個模型元素。
DI的概念
A. 上層模組不應該依賴於下層模組,它們共同依賴於一個抽象。
B. 抽象不能依賴於具象,具象依賴於抽象。
執行個體談開
在分層開發中,通常會有這樣的兩個模組:DAL(資料訪問層)和BLL(商務邏輯層) 。 下面就以電子商務系統中的 訂單、產品、使用者 為例來說說這兩個模組之間的依賴關係。
正向依賴
DAL:
public class OrderDao
{
public List<Orders> GetOrderByUserID(int userid)
{
throw new NotImplementedException();
}
public List<Orders> GetOrderByProductID(int productID)
{
throw new NotImplementedException();
}
}
BLL:
public class Order
{
private OrderDao orderDao;//對DAL中OrderDao的引用
public Order(OrderDao orderDao)
{
orderDao = orderDao;
}
public List<Orders> GetOrderByUserID(int userid)
{
List<Orders> list = null;
list = orderDao.GetOrderByUserID(userid);
return list;
}
public List<Orders> GetOrderByProductID(int productID)
{
List<Orders> list = null;
list = orderDao.GetOrderByProductID(productID);
return list;
}
}
BLL中Order持有了DAL中OrderDao的引用,這個時候BLL模組依賴於DAL模組。他們之間構成了緊耦合。如果要更換DAL模組,顯然需要修改BLL中的代碼。
引入抽象
依賴倒置的思想告訴我們上層模組(BLL)和下層模組(DAL)都應當依賴於抽象。那麼我們引入一個抽象模組。
抽象模組:
public interface IOrderDao
{
List<Orders> GetOrderByUserID(int userid);
List<Orders> GetOrderByProductID(int productID);
}
DAL:
public class OrderDao : IOrderDao//繼承於抽象
{
public List<Orders> GetOrderByUserID(int userid)
{
throw new NotImplementedException();
}
public List<Orders> GetOrderByProductID(int productID)
{
throw new NotImplementedException();
}
}
BLL:
public class Order
{
private IOrderDao orderDao;//依賴於抽象
public Order(IOrderDao orderdao)
{
orderDao = orderdao;
}
public List<Orders> GetOrderByUserID(int userid)
{
List<Orders> list = null;
list = orderDao.GetOrderByUserID(userid);
return list;
}
public List<Orders> GetOrderByProductID(int productID)
{
List<Orders> list = null;
list = orderDao.GetOrderByProductID(productID);
return list;
}
}
現在BLL持有了對抽象模組的引用,而DAL也依賴於該抽象模組。抽象模組的引入消除了BLL和DAL之間的依賴。那麼這種方法是否完美呢?
介面的單一性
在一個業務驅動的系統中,如果與訂單相關的業務發生變化,會導致我們去修改 IOrderDao,相應的DAL中的OrderDao 和BLL的Order都會被修改。
什麼原因呢?
上面的這種設計讓我們無法保持一個穩定的介面。物件導向設計中,有這樣的兩個原則:
單一職責原則(SRP):保證對象的細粒度和單一性。
開放-封閉原則(OCP):對於擴充開放,對於更改封閉。
於是有了下面的設計。
抽象模組:
public interface IOrderUserDao
{
List<Orders> GetOrderByUserID(int userid);
}
public interface IOrderProductDao
{
List<Orders> GetOrderByProductID(int productID);
}
DAL:
public partial class OrderDao : IOrderUserDao
{
public List<Orders> GetOrderByUserID(int userid)
{
throw new NotImplementedException();
}
}
public partial class OrderDao : IOrderProductDao
{
public List<Orders> GetOrderByProductID(int productID)
{
throw new NotImplementedException();
}
}
BLL:
public class User
{
private IOrderUserDao orderDao;//依賴於抽象
public User(IOrderUserDao orderdao)
{
orderDao = orderdao;
}
public List<Orders> GetOrderByUserID(int userid)
{
List<Orders> list = null;
list = orderDao.GetOrderByUserID(userid);
return list;
}
}
public class Product
{
private IOrderProductDao orderDao;//依賴於抽象
public Product(IOrderProductDao orderdao)
{
orderDao = orderdao;
}
public List<Orders> GetOrderByProductID(int productID)
{
List<Orders> list = null;
list = orderDao.GetOrderByProductID(productID);
return list;
}
}
那麼您的意見呢?
作者:青羽