監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設(shè)計管理系統(tǒng) | 簽約案例 | 購買價格 | 在線試用 | 手機APP | 產(chǎn)品資料
X 關(guān)閉

OO設(shè)計原則 -- Dependency Inversion Principle:OO設(shè)計的 DIP依賴倒置原則

申請免費試用、咨詢電話:400-8352-114

 

依賴倒置原則的2個重要方針

A. High level modules should not depend upon low level modules. Both shoulddepend upon abstractions.

高層模塊不應(yīng)該依賴于低層模塊,二者都應(yīng)該依賴于抽象
B. Abstractions should not depend upon details. Details should depend uponabstractions.
抽象不應(yīng)該依賴于細節(jié),細節(jié)應(yīng)該依賴于抽象

 

概念解說:

依賴:在程序設(shè)計中,如果一個模塊a使用/調(diào)用了另一個模塊b,我們稱模塊a依賴模塊b。

低層模塊:往往在一個應(yīng)用程序中,我們有一些低層次的類,這些類實現(xiàn)了一些

基本的或初級的操作,我們稱之為低層模塊;

高層模塊:另外有一些高層次的類,這些類封裝了某些復(fù)雜的邏輯,并且依賴于

低層次的類,這些類我們稱之為高層模塊。

 

我們現(xiàn)在來看看依賴有幾種,依賴也就是耦合,分為下面三種:

----- 零耦合(Nil Coupling)關(guān)系,兩個類沒有依賴關(guān)系,那就是零耦合。

----- 具體耦合(Concrete Coupling)關(guān)系,兩個具體的類之間有依賴關(guān)系,

那么就是具體耦合關(guān)系,如果一個具體類直接引用另外一個具體類就會發(fā)

生這種關(guān)系。

-----抽象耦合(Abstract Coupling)關(guān)系,這種關(guān)系發(fā)生在一個具體類和一個抽

象類之間,這樣就使必須發(fā)生關(guān)系的類之間保持最大的靈活性。


為什么叫做依賴倒置(DependencyInversion)呢?
面向?qū)ο蟪绦蛟O(shè)計相對于面向過程(結(jié)構(gòu)化)程序設(shè)計而言,依賴關(guān)系被倒置了。因為傳統(tǒng)的結(jié)構(gòu)化程序設(shè)計中,高層模塊總是依賴于低層模塊。

 

依賴倒置(Dependence InversionPrinciple)原則講的是:要依賴于抽象,不要依賴于具體。

簡單的說,依賴倒置原則要求客戶端依賴于抽象耦合。原則表述:

抽象不應(yīng)當依賴于細節(jié);細節(jié)應(yīng)當依賴于抽象;

要針對接口編程,不針對實現(xiàn)編程。

 

問題的提出

Robert C. Martin氏在原文中給出了“Bad Design”的定義:
1. It is hard to change because every change affects too many other parts ofthe system.(Rigidity)
系統(tǒng)很難改變,因為每個改變都會影響其他很多部分。
2. When you make a change, unexpected parts of the system break. (Fragility)
當你對某地方做一修改,系統(tǒng)的看似無關(guān)的其他部分都不工作了。
3. It is hard to reuse in another application because it cannot be disentangledfrom the current application. (Immobility)
系統(tǒng)很難被另外一個應(yīng)用重用,因為你很難將要重用的部分從系統(tǒng)中分離開來。

導(dǎo)致“Bad Design”的很大原因是“高層模塊”過分依賴“低層模塊”。
一個良好的設(shè)計應(yīng)該是系統(tǒng)的每一部分都是可替換的。
如果“高層模塊”過分依賴“低層模塊”:

一方面一旦“低層模塊”需要替換或者修改,“高層模塊”將受到影響;

另一方面,高層模塊很難可以重用。

比如,一個Copy模塊,需要把來自Keyboard的輸入復(fù)制到Print,

即使對Keyboard和Print的封裝已經(jīng)做得非常好,但如果Copy模塊里直接使用Keyboard與Print,

Copy任很難被其他應(yīng)用環(huán)境(比如需要輸出到磁盤時)重用。

問題的解決:

為了解決上述問題,Robert C. Martin氏提出了OO設(shè)計的Dependency Inversion Principle (DIP) 原則。

DIP給出了一個解決方案:

在高層模塊與低層模塊之間,引入一個抽象接口層。


High Level Classes(高層模塊)  -->

Abstraction Layer(抽象接口層) -->

Low Level Classes(低層模塊)


抽象接口是對低層模塊的抽象,低層模塊繼承或?qū)崿F(xiàn)該抽象接口。
這樣,高層模塊不直接依賴低層模塊,高層模塊與低層模塊都依賴抽象接口層。
當然,抽象也不依賴低層模塊的實現(xiàn)細節(jié),低層模塊依賴(繼承或?qū)崿F(xiàn))抽象定義。

Robert C. Martin氏給出的DIP方案的類的結(jié)構(gòu)圖:


PolicyLayer -->

MechanismInterface(abstract) -->

MechanismLayer -->

UtilityInterface(abstract) -->

UtilityLayer


類與類之間都通過Abstract Layer來組合關(guān)系。

 

 實例說明DIP

反面例子:


缺點:耦合太緊密,Light發(fā)生變化將影響ToggleSwitch。

解決辦法一:
將Light作成Abstract,然后具體類繼承自Light。


優(yōu)點:ToggleSwitch依賴于抽象類Light,具有更高的穩(wěn)定性,而BulbLight與TubeLight繼承自Light,可以根 據(jù)"開放-封閉"原則進行擴展。只要Light不發(fā)生變化,BulbLight與TubeLight的變化就不會波及ToggleSwitch。

缺點:如果用ToggleSwitch控制一臺電視就很困難了。總不能讓TV繼承自Light吧。

解決方法二:



優(yōu)點:更為通用、更為穩(wěn)定。

 

總結(jié)

 

 DIP要求客戶端依賴于抽象耦合,抽象不應(yīng)當依賴于細節(jié),細節(jié)應(yīng)當依賴于抽象(Abstractionsshould not depend upon details. Details should depend upon abstractions),這 個原則的另外一個表述就是"四人團"強調(diào)的那個:要針對接口編程,不要對實現(xiàn)編程(Program to aninterface, not an implementation),程序在需要引用一個對象時,應(yīng)當盡可能的使用抽象類型作為變量的靜態(tài)類型,這就是針對接口編程的含義。DIP是達到"開-閉"原則的途徑。

要做到DIP,用抽象方式耦合是關(guān)鍵。由于一個抽象耦合總要涉及具體類從抽象類繼承。并且需要保證在任何引用到某類的地方都可以改換成其子類,因此,LSP是DIP的基礎(chǔ)。DIP是OOD的核心原則,設(shè)計模式的研究和應(yīng)用都是用它作為指導(dǎo)原則的。DIP雖然強大,但是也很難實現(xiàn)。另外DIP是假定 所有的具體類都會變化,這也不是全對,有些具體類就相當穩(wěn)定。使用這個類的客戶端就完全可以依賴這個具體類而不用再弄一個抽象類。





發(fā)布:2007-04-17 09:47    編輯:泛普軟件 · xiaona    [打印此頁]    [關(guān)閉]

泛普商業(yè)銷售管理軟件其他應(yīng)用

外貿(mào)行業(yè) 外貿(mào)管理軟件 服裝銷售管理軟件 零售管理系統(tǒng) 汽車銷售管理系統(tǒng) 售后管理系統(tǒng) 電話銷售管理系統(tǒng) 電腦銷售管理軟件 門店銷售管理軟件 分銷管理系統(tǒng) 商業(yè)銷售管理軟件 行銷支持管理系統(tǒng) 商品銷售管理系統(tǒng)