## 連載:面向對象葵花寶典:思想、技巧與實踐(34) - DIP原則
DIP,dependency?inversion?principle**,中文翻譯為“依賴倒置原則”。**
DIP是大名鼎鼎的Martin大師提出來的,他在1996?5月的C++?Reporter發表“?The?Dependency?Inversion?Principle”的文章詳細闡述了DIP原則,并且在他的經典著作《?Agile?Software?Development,?Principles,?Patterns》(中文翻譯為:敏捷軟件開發:原則、模式與實踐)、《Practices,?and?Agile?Principles,?Patterns,?and?Practices?in?C#》(中文翻譯為:敏捷軟件開發:原則、模式與實踐(C#版))中詳細解釋了DIP原則。
?
DIP原則主要有兩點含義:
1)?高層模塊不應該直接依賴低層模塊,兩者都應該依賴抽象層;
2)?抽象不能依賴細節,細節必須依賴抽象;
?
雖然DIP原則的解釋非常清楚,但要真正理解也不那么簡單,因為有幾個關鍵的術語都比較抽象,我們需要更詳細的解析:
1)什么是模塊?
英文中用到了module、component,但我們這是在講類的設計原則,為什么要把DIP拉進來呢?
其實Martin大師只是講一個設計原則而已,這個原則可以應用到軟件系統不同的層級。
例如:站在架構層的角度,模塊可以指子系統subsystem
站在子系統的角度,模塊可以指module,component
站在模塊的角度:模塊可以指類
所以說,這里的模塊應該是一個廣義的概念,而不是狹義的軟件系統里各個子模塊。
?
2)什么是依賴?
這里的依賴對應到具體的面向對象領域其實包含幾個內容:
高層模塊“依賴”低層模塊:指高層模塊需要調用低層模塊的方法;
高層模塊依賴抽象層:指高層模塊基于抽象層編程;
低層模塊依賴抽象層:指低層模塊繼承(inheritance)或者實現(implementation)抽象層;
細節依賴抽象:其實和上一個依賴是同一個意思;
所以說,大師就是大師啊,一個簡簡單單的“依賴”將各種情況都概括進來了,只是苦了我們這些平凡人,要么導致無法理解,要么導致理解錯誤:(
?
我們以一個簡單樣例來詳細解釋這些依賴,樣例包含一個Player類,代表玩家;ICar接口,代表汽車;Benz、Ford、Chery代表具體的汽車,詳細的代碼如下
【Player】
~~~
package com.oo.oop.dip;
/**
* 玩家,對應DIP中的“高層模塊”
*
*/
public class Player {
/**
* 開福特
* 不好的依賴:對應DIP中的“高層模塊依賴低層模塊”,Player直接使用了Ford類對象作為參數,Ford類修改,Player類【需要】重新編譯測試
*/
public void play(Ford car)
{
car.accelerate();
car.shift();
car.steer();
car.brake();
}
/**
* 開奔馳
* 不好的依賴:對應DIP中的“高層模塊依賴低層模塊”,Player直接使用了Benz類對象作為參數,Benz類修改,Player類【需要】重新編譯測試
*/
public void play(Benz car)
{
car.accelerate();
car.shift();
car.steer();
car.brake();
}
/**
* 開奇瑞
* 不好的依賴:對應DIP中的“高層模塊依賴低層模塊”,Player直接使用了Chery類對象作為參數,Chery類修改,Player類【需要】重新編譯測試
*/
public void play(Chery car)
{
car.accelerate();
car.shift();
car.steer();
car.brake();
}
/**
* 開車
* 好的依賴: 對應DIP中的“高層模塊依賴抽象層”,Player依賴ICar接口,不需要知道具體的車類型,Ford、Benz、Chery類修改,Player類【不需要】重新編譯測試,只有ICar修改的時候Player才需要修改
*/
public void play(ICar car)
{
car.accelerate();
car.shift();
car.steer();
car.brake();
}
}
~~~
【ICar】
~~~
package com.oo.oop.dip;
/**
* 汽車接口,對應DIP中的抽象層
*/
public interface ICar {
/**
* 加速
*/
public void accelerate();
/**
* 換擋
*/
public void shift();
/**
* 轉向
*/
public void steer();
/**
* 剎車
*/
public void brake();
}
~~~
【Benz】
~~~
package com.oo.oop.dip;
/**
* 奔馳,實現了ICar接口,對應DIP中的“低層依賴抽象層”
*
*/
public class Benz implements ICar {
@Override
public void accelerate() {
//加速非常快
System.out.println("Benz accelerate: very fast !!");
}
@Override
public void shift() {
//自動擋
System.out.println("Benz shift: automatic transmission !!");
}
@Override
public void steer() {
//非常平穩
System.out.println("Benz steer: very smooth,ESP && DSC && VSC !!");
}
@Override
public void brake() {
//剎車輔助系統
System.out.println("Benz steer: ABS && EBA && BAS && BA !!");
}
}
~~~
【Ford】
~~~
package com.oo.oop.dip;
/**
* 福特,實現了ICar接口,對應DIP中的“低層依賴抽象層”
*
*/
public class Ford implements ICar {
@Override
public void accelerate() {
//加速快
System.out.println("Ford accelerate: fast !!");
}
@Override
public void shift() {
//手自一體變速器
System.out.println("Ford shift: Tiptronic transmission !!");
}
@Override
public void steer() {
//平穩
System.out.println("Ford steer: smooth,ESP !!");
}
@Override
public void brake() {
//剎車輔助系統
System.out.println("Ford steer: ABS && EBA &!!");
}
}
~~~
【Chery】
~~~
package com.oo.oop.dip;
/**
* 奇瑞,實現了ICar接口,對應DIP中的“低層依賴抽象層”
*
*/
public class Chery implements ICar {
@Override
public void accelerate() {
//加速慢
System.out.println("Chery accelerate: slow !!");
}
@Override
public void shift() {
//手動擋
System.out.println("Chery shift: manual transmission !!");
}
@Override
public void steer() {
//平穩
System.out.println("Chery steer: smooth,ESP && DSC !!");
}
@Override
public void brake() {
//剎車輔助系統
System.out.println("Chery steer: only ABS !!");
}
}
~~~
- 前言
- (1) - 程序設計思想的發展
- (2) - 面向對象語言發展歷史
- (3) - 面向過程 vs 面向對象
- (4) - 面向對象是瑞士軍刀還是一把錘子?
- (5) - 面向對象迷思:面向對象導致性能下降?
- (6) - 不要說你懂“類”
- (7) - “對象”新解
- (8) - “接口” 詳解
- (9) - “抽象類” 詳解
- (10) - “抽象” 詳解
- (11) - “封裝” 詳解
- (12) - “繼承” 詳解
- (13) - “多態” 詳解
- (14) - 面向對象開發技術流程
- (15) - 需求詳解
- (16) - 需求分析終極目的
- (17) - 需求分析518方法
- (18) - 用例分析
- (19) - 功能點提取
- (20) - 用例圖的陷阱
- (21) - SSD
- (22) - 領域模型
- (23) - 領域建模三字經
- (24) - 設計模型
- (25) - 類模型
- (26) - 類模型三板斧
- (27) - 動態模型設計
- (28) - 設計原則:內聚&耦合
- (29) - 高內聚低耦合
- (30) - SRP原則
- (31) - OCP原則
- (32) - LSP原則
- (33) - ISP原則
- (34) - DIP原則
- (35) - NOP原則
- (36) - 設計原則如何用?
- (37) - 設計模式:瑞士軍刀 or 錘子?
- (38) - 設計模式之道
- (39) - 設計原則 vs 設計模式
- (40) - DECORATOR模式
- (完)- 書籍已經出版