澄清理解"依赖倒置"

时间:2015-04-21 00:52:07

标签: java oop design-patterns solid-principles

在查看最重要的答案之后,我发现了这个:

  • 高级模块不应依赖于低级模块。都 应该取决于抽象。
  • 抽象绝不应该依赖 细节。细节应取决于抽象。

我对此的理解是这种设计违反了它?因为 Car 类取决于较低级别的类引擎

public class Car {
    private Engine engine;

    public void run() {
        engine.start()
       // do other stuff
    }
}

public class Engine {
    public void start() {
         // do stuff that will start engine
    }
}

如果它确实违反了它,解决方案是什么?我无法想到另一种选择。

我也很难理解第二部分"抽象绝不应该依赖    细节。细节应取决于抽象。"

3 个答案:

答案 0 :(得分:2)

下面的链接很好地解释了依赖倒置的概念: http://www.oodesign.com/dependency-inversion-principle.html

基本上,它归结为复杂的类,取决于简单类的行为,而不是类本身。在您的示例中,下面将是依赖项反转的良好实现:

interface Movable {
    public void start();
    public void throttleUp();
    public void throttleDown();
    //etc..
}

class Engine implements Movable {
    public void start() {
        //code
    }
    //implement other methods
}

class Car {
    Movable engine;

    public void setEngine(Movable engine) {
        this.engine = engine;
    }

    public void run() {
        engine.start();
        //code...
    }
}

将来你可以创造不同类型的发动机,如汽油,柴油,蒸汽,电动。但只要他们实施Movable,您的Car就不会改变,因为它已经解耦。

答案 1 :(得分:1)

您需要了解运行时依赖性和代码依赖性之间的区别。 Car将始终对Engine实现细节具有运行时依赖性,因为控制流将从Car移动到Engine。

但是,依赖性反转是关于源代码依赖性的。您可以使Engine成为接口或抽象类,不同的子类可以提供自己的start()实现(多态)。这样,您的Car将仅依赖于引擎抽象(在源代码级别上),而不依赖于各种start()实现的细节。 Car编写,编译和部署后,您可以在系统中添加新引擎。

另请注意,这些原则更像是建议,而不是“永远/永不”的规则。用你自己的判断。

答案 2 :(得分:0)

让我重新解释你帖子中已有的所有内容,看看它是否有意义

  1. 对于Car来说,完全可以依赖于Engine的界面,就像你的情况一样(只要注入Engine)。
  2. 像Car这样的高级模块不应该依赖于低级实现细节 - 例如Engine的特定子类,例如JetEngine但它可以依赖于引擎
  3. 像Engine这样的抽象不应该依赖于任何特定的实现(再说一个子类Nut,Bolt或Engine)。