連載:面向對象葵花寶典:思想、技巧與實踐(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 !!"); 
	}

}


================================================ 

轉載請註明出處:http://blog.csdn.net/yunhua_lee/article/details/30749311
================================================ 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章