依賴倒轉原則學習

依賴倒置原則(Dependence Inversion Principle)

1、依賴倒置原則的定義

    1)上層模塊不應該依賴於底層模塊,它們都應該依賴於抽象。

    2)抽象不應該依賴於細節,細節應該依賴於抽象,要針對接口編程,不要針對實現編程。

     Abstractions should not depend upon details,Details should dependupon abstractions.Program to an interface, not animplementation.

     也就是說應當使用接口和抽象類進行變量類型聲明、參數類型聲明、方法返還類型說明,以及數據類型的轉換等。而不要用具體類進行變量的類型聲明、參數類型聲明、方法返還類型說明,以及數據類型的轉換等。要保證做到這一點,一個具體類應當只實現接口和抽象類中聲明過的方法,而不要給出多餘的方法。

 

      基於這個原則,設計類結構的方式應該是從上層模塊到底層模塊遵循這樣的結構:上層類--->抽象層--->底層類。

2、依賴倒置原則與開閉原則的關係

 

“開-閉”原則與依賴倒轉原則是目標和手段的關係。如果說開閉原則是目標,依賴倒轉原則是到達"開閉"原則的手段。如果要達到最好的"開閉"原則,就要儘量的遵守依賴倒轉原則,依賴倒轉原則是對"抽象化"的最好規範。里氏代換原則是依賴倒轉原則的基礎,依賴倒轉原則是里氏代換原則的重要補充。

 3、實例

     下面是一個違反了依賴倒轉原則的例子。我們有一個上層類Manager和底層類Worker。我們需要在程序中添加一個新模塊,因爲有新的特殊的工作者被僱用。爲此,我們創建一個新的類SuperWorker。

     假設Manager是一個包含非常複雜的邏輯的類,現在爲了引入新的SuperWorker,我們需要修改它。讓我們看一下這有哪些缺點:

     (1)我們需要修改Manager類(記住,它是一個非常複雜的類,這需要一些時間和努力)。 
      (2)Manager類的一些現有功能可能會受到影響。 
      (3)需要重做單元測試。
      所有的這些問題需要大量的時間去解決。但是如果程序的設計符合依賴倒轉原則將會非常簡單。意思是我們設計Manager類和一個IWorker接口以及一些實現了該接口的Worker類。當需要添加SuperWorker類時我們只需要讓它實現IWorker接口。

Java代碼
  1. //Dependency Inversion Principle - Bad example     
  2. class Worker {     
  3.     public void work() {     
  4.         // ....working     
  5.     }     
  6. }     
  7.     
  8. class Manager {     
  9.     Worker m_worker;     
  10.     
  11.     public void setWorker(Worker w) {     
  12.         m_worker=w;     
  13.     }     
  14.     
  15.     public void manage() {     
  16.         m_worker.work();     
  17.     }     
  18. }     
  19.     
  20. class SuperWorker {     
  21.     public void work() {     
  22.         //.... working much more     
  23.     }     
  24. }    
//Dependency Inversion Principle - Bad example   
class Worker {   
    public void work() {   
        // ....working   
    }   
}   
  
class Manager {   
    Worker m_worker;   
  
    public void setWorker(Worker w) {   
        m_worker=w;   
    }   
  
    public void manage() {   
        m_worker.work();   
    }   
}   
  
class SuperWorker {   
    public void work() {   
        //.... working much more   
    }   
}  

 

     下面是支持依賴倒轉原則的代碼。在這個新的設計中,我們增加了一個新的抽象層IWork接口。現在,上面的問題得到了解決:

      不需要修改Manager類。

      使對Manager類現有功能的影響最小化。

      不需要對Manager類重新進行單元測試。

Java代碼
  1. //Dependency Inversion Principle - Good example     
  2. interface IWorker {     
  3.     public void work();     
  4. }     
  5.     
  6. class Worker implements IWorker{     
  7.     public void work() {     
  8.         // ....working     
  9.     }     
  10. }     
  11.     
  12. class SuperWorker  implements IWorker{     
  13.     public void work() {     
  14.         //.... working much more     
  15.     }     
  16. }     
  17.     
  18. class Manager {     
  19.     IWorker m_worker;     
  20.     
  21.     public void setWorker(IWorker w) {     
  22.         m_worker=w;     
  23.     }     
  24.     public void manage() {     
  25.         m_worker.work();     
  26.     }     
  27. }    
//Dependency Inversion Principle - Good example   
interface IWorker {   
    public void work();   
}   
  
class Worker implements IWorker{   
    public void work() {   
        // ....working   
    }   
}   
  
class SuperWorker  implements IWorker{   
    public void work() {   
        //.... working much more   
    }   
}   
  
class Manager {   
    IWorker m_worker;   
  
    public void setWorker(IWorker w) {   
        m_worker=w;   
    }   
    public void manage() {   
        m_worker.work();   
    }   
}  

 

4、總結

     應用該原則意味着上層類不直接使用底層類,他們使用接口作爲抽象層。這種情況下上層類中創建底層類的對象的代碼不能直接使用new操作符。可以使用一些創建型設計模式,例如工廠方法,抽象工廠和原型模式。

     模版設計模式是應用依賴倒轉原則的一個例子。

     當然,使用該模式需要額外的努力和更復雜的代碼,不過可以帶來更靈活的設計。不應該隨意使用該原則,如果我們有一個類的功能很有可能在將來不會改變,那麼我們就不需要使用該原則。

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