連載:麵向對象葵花寶典:思想、技巧與實踐(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 !!"); } }
================================================
轉載請注明出處:https://blog.csdn.net/yunhua_lee/article/details/30749311================================================
最後更新:2017-04-03 07:57:05