程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 設計模式六大原則(3)--依賴倒置原則,設計模式六大

設計模式六大原則(3)--依賴倒置原則,設計模式六大

編輯:C#入門知識

設計模式六大原則(3)--依賴倒置原則,設計模式六大


定義:

高層次的模塊不應該依賴於低層次的模塊,兩者都應該依賴於抽象接口;抽象接口不應該依賴於具體實現。而具體實現則應該依賴於抽象接口。依賴倒置原則英文全稱為Dependence Inversion Principle,簡稱為DIP。

問題由來:

類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責復雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。

解決方案:

將類A修改為依賴接口I,類B和類C各自實現接口I,類A通過接口I間接與類B或者類C發生聯系,則會大大降低修改類A的幾率。

采用依賴倒置原則可以減少類間的耦合性,提高系統的穩定性,減少並行開發引起的風險,提高代碼的可讀性和可維護性。依賴倒置原則的核心就是面向接口編程,理解了面向接口編程也就理解了依賴倒置原則。下面通過一個司機開車的例子簡單說明一下:

有一個奔馳車類,奔馳車可以運行,方法為Run,司機類有一個開奔馳車的方法Drive。司機和奔馳車類的代碼如下所示:

///<summary>

/// 奔馳車類

///</summary>

public class Benz

{

//奔馳車運行

public void Run()

{

Console.WriteLine("奔馳車開始運行...");

}

}

///<summary>

/// 司機類

///</summary>

public class Driver

{

public void Drive(Benz benz)

{

benz.Run();

}

}

 

主函數司機小明開動奔馳車,代碼如下:

class Client

{

static void Main(string[] args)

{

//一輛奔馳車

var benz = new Benz();

//司機小明

var xiaoming = new Driver();

//小明開奔馳

xiaoming.Drive(benz);

Console.ReadKey();

}

}

 

上面實現了司機開奔馳車的場景,但是對於實際的業務來說,需求是不斷變化的。在技術上"變更才顯真功夫",只有在"變化"過程中才能知道自己設計或程序是否是松耦合。上面的例子,我們加點要求:司機也要會開寶馬車。要完成這個必須先有個寶馬車類,如下所示:

///<summary>

/// 寶馬車類

///</summary>

public class Bmw

{

//寶馬車運行

public void Run()

{

Console.WriteLine("寶馬車開始運行...");

}

}

 

盡管有了寶馬車類,但是司機根本木有開寶馬車的方法。你可能會說,木有那就加上開寶馬車的方法!這樣,是解決了一時的問題,但是還有法拉利、賓利等車呢?因此,是我們的設計出現了問題:司機類和奔馳車類之間是一個緊耦合的關系,其導致的結果就是系統的可維護性大大降低,可讀性降低,兩個相似的類需要閱讀兩個文件,這顯然不可取。還有穩定性:固化的、健壯的才是穩定的。這裡只是增加了一個車類就需要修改司機類,這不是穩定性,這是易變性。被依賴者的變更竟然讓依賴者來承擔修改的成本,這樣的依賴關系誰肯承擔!

在實際項目的開發中,要盡可能減少並行開發引起的風險。並行開發最大的風險就是風險擴散,本來只是一段程序的錯誤或異常,逐步波及一個功能,一個模塊,甚至到最後毀壞了整個項目。因為一個團隊,幾十人甚至上百人人開發,各人負責不同的功能模塊,甲負責汽車類的建造,乙負責司機類的建造,在甲沒有完成的情況下,乙是不能完全地編寫代碼的,缺少汽車類,編譯器根本就不會讓你通過!在缺少Benz類的情況下,Driver類能編譯嗎?更不要說是單元測試了!這種相互依存的關系在實際開發中是不被允許的,另一個角度來說這樣開發只能挨個進行修改,並且每一項修改可能牽一發而動全身。這種模式 在現在的大中型項目中已經是完全不能勝任了,一個項目是一個團隊的協作結果,一個人不可能了解所有的業務和所有的技術,要協作就要並行開發,要並行開發就要解決模塊之間的項目依賴關系,然後依賴倒置原則就隆重出場了,呵呵。

依賴倒置原則的核心就是接口,下面我們為車和司機定義兩個接口ICar和IDriver,代碼如下所示:

///<summary>

/// 汽車接口

///</summary>

public interface ICar

{

void Run();

}

///<summary>

/// 司機接口

///</summary>

public interface IDriver

{

void Drive(ICar car);

}

 

然後讓上面定義的司機和汽車(寶馬和奔馳)各自繼承自己對應的接口,代碼如下所示:

///<summary>

/// 奔馳車類

///</summary>

public class Benz:ICar

{

//奔馳車運行

public void Run()

{

Console.WriteLine("奔馳車開始運行...");

}

}

///<summary>

/// 寶馬車類

///</summary>

public class Bmw:ICar

{

//寶馬車運行

public void Run()

{

Console.WriteLine("寶馬車開始運行...");

}

}

///<summary>

/// 司機類

///</summary>

public class Driver:IDriver

{

public void Drive(ICar car)

{

car.Run();

}

}

 

此時的類的結構圖如下所示:

在開發實現業務需求時,我們應該謹記抽象不依賴細節。在這裡,汽車和司機的接口都不依賴細節(具體的實現類),看到這應該對依賴倒置原則理解的差不多了吧。

依賴倒置原則是一個指導思想,是通過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的松耦合,為更好使用此原則,在實際項目中我們要按如下方法使用:

 

  • 每一個類都要盡可能有接口或抽象類和兩者都有,也不可過分去生搬硬套依賴倒置原則。
  • 變量的顯示類型盡量是接口或者抽象類。

 

 

  • 任何類都不要從具體類中派生。

 

 

  • 盡量不要覆寫基類的方法。

 

 

  • 結合裡氏替換原則使用

 

依賴倒置原則是六個設計原則中最難以實現的原則,它是實現開閉原則的重要途徑,依賴倒置原則沒有實現,就別想實現對擴展開放,對修改關閉。在項目中,大家只要記住是"面向接口編程"就基本上抓住了依賴倒轉原則的核心。順便說一下,實際的項目投產上線和盈利是第一要務,因此設計模式的原則只是提供了指導思想,我們不應該主動去違背,但是限於實際情況不得不違背,否則即便設計得有多麼好,架構多麼完美,這都是扯淡的事情。一旦超過預期工期或者項目虧本,你老板不高興,然後你也會不高興的…


(java)設計模式中,“依賴倒置原則”說〔要依賴抽象,不要依賴具體類〕這句話中的“依賴”怎理解

同意樓上,像這種簡單的組合關系就是依賴的一種體現。所謂依賴倒置,就是說,依賴的B不是直接通過B b=new B();來獲取,而是先在工廠裡先new好,A什麼時候需要用的時候直接去工廠裡取就是了。
 

面向對象的3個要素,5個原則 與 6視點 都有什?

面向對象三要素
封裝(Encapsulation)
繼承(Inheritance)
多態(Polymorphism)
面向對象五原則
單一職責原則(SRP)
開放-封閉原則(OCP)
Liskov替換原則(LSP)
依賴倒置原則(DIP)
接口隔離原則(ISP)

面向對象六視點
復用(Reusibility)
擴展(Extensibility)
分離(Separability)
變化(Change)
簡約(Simplicity)
一致(Coherance)
應該就這些吧。有問題,可以接著問。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved