依賴倒置原則(依賴倒轉原則)

依賴倒置原則

依賴倒轉原則一般指本詞條

依賴倒置原則(Dependence Inversion Principle)是程式要依賴於抽象接口,不要依賴於具體實現。簡單的說就是要求對抽象進行編程,不要對實現進行編程,這樣就降低了客戶與實現模組間的耦合

基本介紹

  • 中文名:依賴倒置原則
  • 外文名:Dependence Inversion Principle
  • 表達式:要依賴於抽象,不要依賴於具體
  • 適用領域編程開發
意圖,代碼實現,結構圖,

意圖

面向過程的開發,上層調用下層,上層依賴於下層,當下層劇烈變動時上層也要跟著變動,這就會導致模組的復用性降低而且大大提高了開發的成本。
面向對象的開發很好的解決了這個問題,一般情況下抽象的變化機率很小,讓用戶程式依賴於抽象,實現的細節也依賴於抽象。即使實現細節不斷變動,只要抽象不變,客戶程式就不需要變化。這大大降低了客戶程式與實現細節的耦合度
面向對象思想的結構圖
依賴倒置原則
圖一
背景1:公司是福特本田公司的金牌合作夥伴,現要求開發一套自動駕駛系統,只要汽車上安裝該系統就可以實現無人駕駛,該系統可以在福特和本田車上使用,只要這兩個品牌的汽車使用該系統就能實現自動駕駛。於是有人做出了分析如圖一。
對於圖一分析:我們定義了一個AutoSystem類,一個FordCar類,一個HondaCar類。FordCar類和HondaCar類中各有三個方法:Run(啟動Car)、Turn(轉彎Car)、Stop(停止Car),當然了一個汽車肯定不止這些功能,這裡只要能說明問題即可。AutoSystem類是一個自動駕駛系統,自動操縱這兩輛車。

代碼實現

public class HondaCar{
    public void Run(){
        Console.WriteLine("本田開始啟動了");
    }
    public void Turn(){
        Console.WriteLine("本田開始轉彎了");
    }
    public void Stop(){
        Console.WriteLine("本田開始停車了");
    }
}
public class FordCar{
    public void Run(){
        Console.WriteLine("福特開始啟動了");
    }
    public void Turn(){
        Console.WriteLine("福特開始轉彎了");
    }
    public void Stop(){
        Console.WriteLine("福特開始停車了");
    }
}
public class AutoSystem{
    public enum CarType{
        Ford,Honda
    };
    private HondaCar hcar=new HondaCar();
    private FordCar fcar=new FordCar();
    private CarType type;
    public AutoSystem(CarType type){
        this.type=type;
    }
    public void RunCar(){
        if(type==CarType.Ford){
            fcar.Run();
        } else {
            hcar.Run();
        }
    }
    public void TurnCar(){
        if(type==CarType.Ford){
            fcar.Turn();
        } else { 
            hcar.Turn();
        }
    }
    public void StopCar(){
        if(type==CarType.Ford){
            fcar.Stop();
            } else {
                hcar.Stop();
            }
    }
}
代碼分析:上面的程式確實能夠實現針對Ford和Honda車的無人駕駛,但是軟體是在不斷變化的,軟體的需求也在不斷的變化。
背景2:公司的業務做大了,同時成為了通用、三菱、大眾的金牌合作夥伴,於是公司要求該自動駕駛系統也能夠安裝在這3種公司生產的汽車上。於是我們不得不變動AutoSystem:
public class AutoSystem{
public enum CarType{
Ford,Honda,Bmw
};
HondaCar hcar=new HondaCar();
FordCarf car=new FordCar();
BmwCar bcar=new BmwCar();
private CarType type;
public AutoSystem(CarTypetype){
this.type=type;
}
public void RunCar(){
if(type==CarType.Ford){
fcar.Run();
}
else if(type==CarType.Honda){
hcar.Run();
}
else if(type==CarType.Bmw){
bcar.Run();
}
}
public void TurnCar(){
if(type==CarType.Ford){
fcar.Turn();
}
else if(type==CarType.Honda){
hcar.Turn();
}
else if(type==CarType.Bmw){
bcar.Turn();
}
}
public void StopCar(){
if(type==CarType.Ford){
fcar.Stop();
}
else if(type==CarType.Honda){
hcar.Stop();
}
else if(type==CarType.Bmw){
bcar.Stop();
}
}
}
分析:這會給系統增加新的相互依賴。隨著時間的推移,越來越多的車種必須加入到AutoSystem中,這個“AutoSystem”模組將會被if/else語句弄得很亂,而且依賴於很多的低層模組,只要低層模組發生變動,AutoSystem就必須跟著變動,
它最終將變得僵化、脆弱。
導致上面所述問題的一個原因是,含有高層策略的模組,如AutoSystem模組,依賴於它所控制的低層的具體細節的模組(如HondaCar和FordCar)。如果我們能夠找到一種方法使AutoSystem模組獨立於它所控制的具體細節,那么我們就可以自由地復用它了。我們就可以用這個模組來生成其它的程式,使得系統能夠用在需要的汽車上。OOD給我們提供了一種機制來實現這種“依賴倒置”。

結構圖

這兒有一個“AutoSystem”類,它包含一個“ICar”接口。這個“AutoSystem”類根本不依賴於“FordCar”和“HondaCar”。所以,依賴關係被“倒置”了:“AutoSystem”模組依賴於抽象,那些具體的汽車操作也依賴於相同的抽象。
於是可以添加ICar
public interface ICar
{
void Run();
void Turn();
void Stop();
}
public class BmwCar:ICar
{
public void Run()
{
Console.WriteLine("寶馬開始啟動了");
}
public void Turn()
{
Console.WriteLine("寶馬開始轉彎了");
}
public void Stop()
{
Console.WriteLine("寶馬開始停車了");
}
}
public class FordCar:ICar
{
publicvoidRun()
{
Console.WriteLine("福特開始啟動了");
}
public void Turn()
{
Console.WriteLine("福特開始轉彎了");
}
public void Stop()
{
Console.WriteLine("福特開始停車了");
}
}
public class HondaCar:ICar
{
publicvoidRun()
{
Console.WriteLine("本田開始啟動了");
}
public void Turn()
{
Console.WriteLine("本田開始轉彎了");
}
public void Stop()
{
Console.WriteLine("本田開始停車了");
}
}
public class AutoSystem
{
private ICar icar;
public AutoSystem(ICar icar)
{
this.icar=icar;
}
private void RunCar()
{
icar.Run();
}
private void TurnCar()
{
icar.Turn();
}
private void StopCar()
{
icar.Stop();
}
}
AutoSystem系統依賴於ICar 這個抽象,而與具體的實現細節HondaCar、FordCar、BmwCar無關,所以實現細節的變化不會影響AutoSystem。對於實現細節只要實現ICar 即可,即實現細節依賴於ICar 抽象。
綜上:
一個套用中的重要策略決定及業務模型正是在這些高層的模組中。也正是這些模型包含著套用的特性。但是,當這些模組依賴於低層模組時,低層模組的修改將會直接影響到它們,迫使它們也去改變。這種境況是荒謬的。應該是處於高層的模組去迫使那些低層的模組發生改變。應該是處於高層的模組優先於低層的模組。無論如何高層的模組也不應依賴於低層的模組。而且,我們想能夠復用的是高層的模組。通過子程式庫的形式,我們已經可以很好地復用低層的模組了。當高層的模組依賴於低層的模組時,這些高層模組就很難在不同的環境中復用。但是,當那些高層模組獨立於低層模組時,它們就能很簡單地被復用了。這正是位於框架設計的最核心之處的原則。
總結:依賴倒置原則
A.高層次的模組不應該依賴於低層次的模組,他們都應該依賴於抽象。
B.抽象不應該依賴於具體,具體應該依賴於抽象。

相關詞條

熱門詞條

聯絡我們