依赖倒置原理和组成

jus*_*dev 4 oop dependency-injection solid-principles

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

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

谢谢.

Jan*_*nis 8

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

如果在类中创建对象,则此类与创建的类紧密耦合.如果不更改创建另一个的类,则无法交换实现.

例: 在此输入图像描述

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

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

public class Client {
    private Server server;

    public Client(){
        this.server = new Server();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Client {
    private AnotherServer anotherServer;

    public Client(){
        this.anotherServer = new AnotherServer();
    }
}
Run Code Online (Sandbox Code Playgroud)

这告诉您,Client类高度依赖于类Server.

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

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

例: 在此输入图像描述

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

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

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

client.setServer(new SecondServer());
...
Run Code Online (Sandbox Code Playgroud)

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

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

因为具体服务器"FirstServer"和"SecondServer"实现了ClientServer接口,所以它们也依赖于该接口.并且因为继承是比组合更强的依赖,所以具体的服务器类比Client类更依赖于接口.

这就是依赖性被颠倒的原因.具体的服务器类现在依赖于"Client-ClientServer"--clomelomerate.

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