依赖倒转原则学习

依赖倒置原则(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操作符。可以使用一些创建型设计模式,例如工厂方法,抽象工厂和原型模式。

     模版设计模式是应用依赖倒转原则的一个例子。

     当然,使用该模式需要额外的努力和更复杂的代码,不过可以带来更灵活的设计。不应该随意使用该原则,如果我们有一个类的功能很有可能在将来不会改变,那么我们就不需要使用该原则。

你可能感兴趣的:(基础学习篇,java,类,面向对象)