依赖倒置原则和构成

时间:2017-01-28 10:15:03

标签: oop dependency-injection solid-principles

我正在阅读关于SOLID原则的内容,我在此处停止了“依赖性倒置原则”,这意味着对象应该已经通过实例化到另一个对象,这意味着组合不能应用依赖性倒置原则对吗?或者有什么我想念的? 更新************************************************* * 假设你有一个类,这个类有一个引用anther对象的属性,我们有2个解决方案(对我来说):

  1. 在类外创建对象并将其传递给类。(依赖项)
  2. 在类中自己创建对象(合成)。
  3. 谢谢。

2 个答案:

答案 0 :(得分:7)

你的困惑来自于你对构图的理解。另一个拥有的对象取决于拥有对象的生命周期。这并不意味着你必须在拥有类中创建拥有的对象。

如果在类中创建对象,则此类与创建的类紧密耦合。你不能在不改变创造另一个的类的情况下交换实现。

实施例: enter image description here

在上图中,您有类Client,它使用类Server。假设这是一个组合,客户端具有Server类型的属性。

如果在客户端类中创建类服务器的实例,它可能如下所示:

public class Client {
    private Server server;

    public Client(){
        this.server = new Server();
    }
}

现在假设你要交换服务器的实现。您需要更改Client类的实现,因为交换它的唯一方法是创建另一个类的实例(可能称为AnotherServer)。

public class Client {
    private AnotherServer anotherServer;

    public Client(){
        this.anotherServer = new AnotherServer();
    }
}

这表明,Client类高度依赖于类Server。

为了轻松更改服务器的已使用实现并因此修改客户端的行为,最好从抽象(抽象类或接口)中组合客户端。这样做意味着您无法在拥有类中创建所需的对象,因为您只能创建具体的类。创建类意味着调用构造函数并依赖于创建的类。

实现组合的更好方法( - 客户端由服务器组成 - )是通过setter方法或构造函数注入它。像这样你可以隐藏接口背后的实现类。

实施例: enter image description here

在第二张图片中,我们保护客户免受有关服务器具体实现的了解。它只取决于服务器接口。这种依赖性并不那么引人注目,因为客户端定义了接口。他决定了Server接口所需的功能。为了表明服务器的接口属于客户端,它被称为" ClientServer"。

要编写客户端,您必须为类外部的ClientServer接口创建具体类,并通过构造函数或setter方法注入它。

...
FirstServer first = new FirstServer();
Client client = new Client(first);

client.setServer(new SecondServer());
...

像这样,即使在运行时,您也可以轻松地在客户端中交换使用过的Server实现。

这种机制称为依赖性倒置原则(DIP)。但为什么? Client类仍然依赖于服务器接口。如果界面发生变化,客户也必须更改。是的,这是正确的。但客户决定在该界面中需要哪些功能。因此,当客户端说需要更改时,通常会更改界面。由于客户端更改,接口会更改。

因为具体服务器" FirstServer"和#34; SecondServer"实现它们依赖于该接口的ClientServer接口。而且因为继承是一种比组合更强的依赖,所以具体的服务器类比Client类更依赖于接口。

这就是为什么依赖性被颠倒了。具体的服务器类现在依赖于" Client-ClientServer" -conglomerate。

因此,您的问题的答案是:当您在另一个班级中创建班级时,您无法达到DIP。但是你可以通过定义一个注入继承这个接口的具体类的接口来达到DIP的组合。

答案 1 :(得分:3)

采取from Wikipedia

  

一个。高级模块不应该依赖于低级模块。两者都应该取决于抽象。

     

B中。抽象不应该依赖于细节。细节应该取决于抽象。

你说:

  

表示对象应该已经实例化到另一个对象

依赖性反转原则与类构造函数之类的编程实现细节没有任何关系,它们用于初始化正在构造的对象。

除非您将构造函数参数定义为实现而不是抽象,并且/或者注入的依赖项具有比目标依赖项更高的层,否则您不会违反整个原则。