面向对象设计的原则------依赖倒置原则

依赖倒置原则(Dependence Inversion Principle)

1、依赖倒置原则的定义

     1)上层模块不应该依赖于底层模块,它们都应该依赖于抽象。

     2)抽象不应该依赖于细节,细节应该依赖于抽象,要针对接口编程,不要针对实现编程。

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

      也就是说应当使用接口和抽象类进行变量类型声明、参数类型声明、方法返还类型说明,以及数据类型的转换等。而不要用具体类进行变量的类型声明、参数类型声明、方法返还类型说明,以及数据类型的转换等。要保证做到这一点,一个具体类应当只实现接口和抽象类中声明过的方法,而不要给出多余的方法。

      基于这个原则,设计类结构的方式应该是从上层模块到底层模块遵循这样的结构:上层类--->抽象层--->底层类。

2、依赖倒置原则与开闭原则的关系

-原则与依赖倒转原则是目标和手段的关系。如果说开闭原则是目标,依赖倒转原则是到达"开闭"原则的手段。如果要达到最好的"开闭"原则,就要尽量的遵守依赖倒转原则,依赖倒转原则是对"抽象化"的最好规范。里氏代换原则是依赖倒转原则的基础,依赖倒转原则是里氏代换原则的重要补充。

 3、实例

      下面是一个违反了依赖倒转原则的例子。我们有一个上层类Manager和底层类Worker。我们需要在程序中添加一个新模块,因为有新的特殊的工作者被雇用。为此,我们创建一个新的类SuperWorker。

      假设Manager是一个包含非常复杂的逻辑的类,现在为了引入新的SuperWorker,我们需要修改它。让我们看一下这有哪些缺点:

      (1)我们需要修改Manager类(记住,它是一个非常复杂的类,这需要一些时间和努力)。 
      (2)Manager类的一些现有功能可能会受到影响。 
      (3)需要重做单元测试。
       所有的这些问题需要大量的时间去解决。但是如果程序的设计符合依赖倒转原则将会非常简单。意思是我们设计Manager类和一个IWorker接口以及一些实现了该接口的Worker类。当需要添加SuperWorker类时我们只需要让它实现IWorker接口。

//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类重新进行单元测试。

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

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

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

你可能感兴趣的:(设计模式,数据结构,编程,工作,单元测试)