一、定義
1.高層子產品不應該依賴低層子產品,二者都應該依賴抽象
2.抽象不應該依賴于細節。細節應該依賴于抽象
二、階層化
1.簡單介紹
結構良好的面向對象架構都具有清晰的層次定義,每個層次通過一個定義良好的、受控的接口向外提供了一組内聚的服務。
對于這個陳述的簡單了解可能會緻使設計者設計出類似下圖的結構。
圖中,高層的Policy層使用了低層的Mechanism層,而Mechanism層又使用了更細節的Utility層。這樣,Policy層對下面的Utility層的改動都是敏感的。 這種依賴關系是傳遞的。這是非常糟糕的。
下圖則展示了一個更為合适的模型。 每個較高層次都為它所需要的服務聲明一個抽象接口。較低的層次實作了這些抽象接口。每個高層類都通過該抽象接口使用下一層,這樣高層就不依賴于低層。低層反而依賴于在高層中聲明的抽象服務接口。這解除了Policy層、Mechanism層和Utility層的兩兩依賴關系。
2.倒置的接口所有權
這裡的倒置不僅僅是依賴關系的倒置,它也是接口所有權的倒置。
但是當應用DIP時,我們發現往往是客戶擁有抽象接口,而它們的服務者則從這些抽象接口派生。
這就是著名的Hollywood(好萊塢)原則:"Don't call us,we'll call you.(不要找我們,我們會去找你)"。
低層子產品實作了在高層子產品中聲明并被高層子產品調用的接口。
Hollywood原則解釋:
//不應用IOC
class A
{
B b = new B();
}
//應用IOC
class A
{
B b = null; // 你不需要自己找B,當你需要的時候,B會自動替你初始化。
public A(B b)
{
this.b=b;
}
}
通過這種導緻的接口所有權,對于Mechanism層或者Utility層的任務改動都不會再影響到Policy層。而且,Policy層可以定義符合policyServiceInstance的任何上下文重用。通過倒置這些依賴關系,我們建立了一個更靈活、更持久、更易改變的結構。
3.依賴于抽象
依賴于抽象建議我們不應該依賴于具體類--也就是說,程式中所有的依賴關系都應該終止于抽象類或者接口。
- 任何變量都不應該持有一個指向具體類的引用
- 任何類都不應該從具體類派生
- 任何方法都不應該重寫它的任何基類中的已實作了的方法 有時必須建立具體類的執行個體,而建立的子產品将會依賴它們,如果一個具體的類不太會改變,并且也不會建立其他類似的派生類,那麼依賴于它并不會造成損害。
三、結論
事實上,這種依賴關系的導緻正是好的面向對象設計的标志所在。使用何種語言來編寫程式是無關緊要的。如果程式的依賴關系是倒置的,他就是面向對象的設計。如果程式的依賴關系不是倒置的,他就是過程化設計。