C#實現(xiàn)六大設計原則之依賴倒置原則
依賴倒置原則(DIP)定義:
高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節(jié);細節(jié)應該依賴抽象。
問題由來:
類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,
負責復雜的業(yè)務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。
解決方案:
將類A修改為依賴接口I,類B和類C各自實現(xiàn)接口I,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系,則會大大降低修改類A的幾率。
ps:
依賴倒置原則基于這樣一個事實:相對于細節(jié)的多變性,抽象的東西要穩(wěn)定的多。以抽象為基礎搭建起來的架構比以細節(jié)為基礎
搭建起來的架構要穩(wěn)定的多。抽象指的是接口或者抽象類,細節(jié)就是具體的實現(xiàn)類,使用接口或者抽象類的目的是制定
好規(guī)范和契約,而不去涉及任何具體的操作,把展現(xiàn)細節(jié)的任務交給他們的實現(xiàn)類去完成。
依賴倒置原則的核心思想是面向接口編程,用一個例子來說明面向接口編程比相對于面向實現(xiàn)編程好在什么地方。
舉個生活中的例子, 我們每天下班, 可能為了方便亦或鍛煉身體, 選擇騎單車回家, 對于現(xiàn)在單車, 又有各種各樣: mobike, ofo, 小藍, 小鳴等等...
(用C#代碼表達) 定義3個實現(xiàn), 分別對應的是各種單車品牌。
public class BlueGoGo
{
public void Go()
{
Console.WriteLine("騎的是小藍單車");
}
}
public class Ofo
{
public void Go()
{
Console.WriteLine("騎的是小黃單車");
}
}
public class Mobike
{
public void Go()
{
Console.WriteLine("騎的是摩拜單車");
}
}然后再定義一個騎行類(Ride)
//騎行類
public class Ride
{
//掃碼小藍騎車
public void ScanCodeByBlueGoGo()
{
BlueGoGo blue = new BlueGoGo();
blue.Go();
}
//掃碼摩拜單騎車
public void ScanCodeByMoBike()
{
Mobike mo = new Mobike();
mo.Go();
}
//掃碼小黃騎車
public void ScanCodeByOfo()
{
Ofo ofo = new Ofo();
ofo.Go();
}
}現(xiàn)在看上去確實也沒什么問題, 所以調用一下, 一切正常

仔細看看, 這個代碼確實有問題, 針對上面所講的依賴倒置原則
<類A直接依賴類B, 假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責復雜的業(yè)務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。>
正如例子中的 騎行類(Ride) 正是依賴BlueGoGo,MoBike,Ofo類, 如果現(xiàn)在 Ride類要新增一個小鳴單車, 則我們必須要修改Ride的代碼,同是添加一個XiaoMing的類達到效果。
//騎行類
public class Ride
{
//掃碼小藍騎車
public void ScanCodeByBlueGoGo()
{
BlueGoGo blue = new BlueGoGo();
blue.Go();
}
//掃碼摩拜單騎車
public void ScanCodeByMoBike()
{
Mobike mo = new Mobike();
mo.Go();
}
//掃碼小黃騎車
public void ScanCodeByOfo()
{
Ofo ofo = new Ofo();
ofo.Go();
}
/*
* 該功能位新增的小鳴單車, 必須修改Ride類
*/
public void ScanCodeByXiaoMing()
{
XiaoMing xming = new XiaoMing();
xming.Go();
}
}像MoBike, BlueGoGo, Ofo, XiaoMing 這些類, 他們都屬于底層模塊, 負責基本的騎車的動作, 按照依賴倒置的原則, 則不應該修改A, 否則如果在業(yè)務量很大的情況下, 則會給程序帶來不必要的潛在風險。
用依賴導致的思想怎么去實現(xiàn) 新增小鳴單車而不對高層模塊進行修改?
1.將單車的每個Go動作都抽象起來, 分別讓他們去做各自的實現(xiàn)。
//修改位抽象的車類
public abstract class abstarctBike
{
public abstract void Go();
}
public class BlueGoGo: abstarctBike
{
public override void Go()
{
Console.WriteLine("騎的是小藍單車");
}
}
public class Ofo : abstarctBike
{
public override void Go()
{
Console.WriteLine("騎的是小黃單車");
}
}
public class Mobike : abstarctBike
{
public override void Go()
{
Console.WriteLine("騎的是摩拜單車");
}
}
public class XiaoMing : abstarctBike
{
public override void Go()
{
Console.WriteLine("騎的是小明單車");
}
}這時, 我們再把騎行類(Ride)進行改造, 將原有的ScanCodeXXX 都棄用, 用一個全新的ScanCode提供一個抽象類型。
//騎行類
public class Ride
{
//
public void ScanCode(abstarctBike bike)
{
bike.Go();
}
/*
* 以下位之前棄用的模式
*/
//掃碼小藍騎車
public void ScanCodeByBlueGoGo()
{
BlueGoGo blue = new BlueGoGo();
blue.Go();
}
//掃碼摩拜單騎車
public void ScanCodeByMoBike()
{
Mobike mo = new Mobike();
mo.Go();
}
//掃碼小黃騎車
public void ScanCodeByOfo()
{
Ofo ofo = new Ofo();
ofo.Go();
}
/*
* 該功能位新增的小鳴單車, 必須修改Ride類
*/
public void ScanCodeByXiaoMing()
{
XiaoMing xming = new XiaoMing();
xming.Go();
}
}現(xiàn)在, 我們再調用, 只要指定給Ride對象ScanCode執(zhí)行的類型就可以實現(xiàn)騎行動作。

這樣修改后,無論以后怎樣擴展單車類,都不需要再修改Ride類了。這只是一個簡單的例子,實際情況中,代表高層模塊的Ride類將負責完成主要的業(yè)務邏輯,
一旦需要對它進行修改,引入錯誤的風險極大。所以遵循依賴倒置原則可以降低類之間的耦合性,提高系統(tǒng)的穩(wěn)定性,降低修改程序造成的風險。
在實際編程中,我們一般需要做到如下3點:
- 低層模塊盡量都要有抽象類或接口,或者兩者都有。
- 變量的聲明類型盡量是抽象類或接口。
- 使用繼承時遵循里氏替換原則。
依賴倒置原則的核心就是要我們面向接口編程,理解了面向接口編程,也就理解了依賴倒置。
到此這篇關于C#實現(xiàn)六大設計原則之依賴倒置原則的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C#把數組中的某個元素取出來放到第一個位置的實現(xiàn)方法
這篇文章主要介紹了C#把數組中的某個元素取出來放到第一個位置的實現(xiàn)方法,涉及C#針對數組的常見操作技巧,非常具有實用價值,需要的朋友可以參考下2014-12-12

