依赖倒置的原理和组成 [英] Dependency inversion principle and composition

查看:91
本文介绍了依赖倒置的原理和组成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读有关SOLID原理的信息,并在这里停止了 依赖反转原理 ,这意味着对象应该已经实例化传递给另一个对象,这意味着组成不能用依赖倒置原则应用的对吗?还是我想念什么?
更新************************************************* *****
假设您有一个类,并且该类有一个引用花药对象的属性,我们有2个解决方案(对我而言):

I am reading about SOLID principles and I stopped here on "Dependency inversion principle" which means the objects should passed already instantiated to anther object, which means composition cannot be applied with Dependency inversion principle am right? or there is something I miss? UPDATE ************************************************** suppose you have a class and this class has an attribute which is reference to anther object, we have 2 solution(for me):


  1. 在类外创建对象并将其传递给类。(依赖关系)

  2. 在类内将对象自身(组成)创建。

谢谢。

推荐答案

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

Your confusion comes from your understanding of composition. The object that is owned by another is dependent of the lifetime of the owning object. That doesn't mean that you have to create the owned object inside the owning class.

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

If you create objects in a class, this class is tightly coupled to the created class. You can't exchange the implementation without changing the class which creates the other.

示例:

在上图中,您有Client类,它使用Server类。可以说这是一个组合,并且客户端具有服务器类型的属性。

In the picture above you have the class Client, which uses the class Server. Lets say this is a composition and the Client has an attribute of the type Server.

如果您在客户端类中创建类服务器的实例,则它看起来可能像这样:

If you create an instance of the class server inside the client class, it could look like this:

public class Client {
    private Server server;

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

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

Now lets say you want to exchange the implementation of the Server. You need to change the implementation of the Client class, because the only way to exchange it, is to create an instance of another class (maybe called AnotherServer).

public class Client {
    private AnotherServer anotherServer;

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

这向您显示,Client类是高度依赖的

This shows you, that the Client class is highly dependent of the class Server.

为了轻松更改Server的使用实现并从而修改Client的行为,最好将Client组成为抽象类(抽象类或接口)。这样做意味着您无法在所属类中创建所需的对象,因为您只能创建具体的类。创建类意味着调用构造函数并依赖于所创建的类。

To easily change the used implementation of the Server and thus modify the Client's behaviour it would be better to compose the Client out of abstractions (abstract classes or interfaces). Doing so means you can't create the needed object in the owning class, because you can only create concrete classes. Creating classes means calling the constructor and being dependent of that class which was created.

一种实现组合的更好方法(– Client由Server组成–)通过setter方法或构造函数注入它。这样,您可以将实现类隐藏在接口后面。

A better way to achieve composition (– the Client is composed out of a Server –) is by injecting it through a setter method or the constructor. Like this you can hide implementation classes behind an interface.

示例:

在第二张图片中,我们保护客户端免受服务器具体实现的了解。它仅取决于服务器接口。这种依赖性不是那么严重,因为客户端定义了接口。他决定服务器接口所需的功能。为了表示服务器的接口属于客户端,它称为 ClientServer。

In the second picture we protect the Client from the knowledge about the Server's concrete implementation. It only depends on the server interface. This dependency is not that dramatic, because the Client defines the interface. He decides about needed function of the Server interface. To indicate, that the interface for the servers belongs to the Client it is called "ClientServer".

要组成您的客户端,必须为ClientServer接口创建具体的类

To compose your Client you have to create the concrete classes for the ClientServer interface outside the class and inject it through the constructor or a setter method.

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

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

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

Like this you can easily exchange the used Server implementation in the Client, even at runtime.

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

This mechanism is called the dependency inversion principle (DIP). But Why? The Client class is still dependent of the server interface. If the interface changes, the Client has to change too. Yes, this is correct. But the Client decides which functions he needs in that interface. So normally the interface changes, when the Client says that it needs to be changed. The interface changes because the Client changes.

因为具体的服务器 FirstServer和 SecondServer实现了接口ClientServer,所以它们也依赖于该接口。并且由于继承比组合更强,因此与客户机类相比,具体的服务器类对接口的依赖性更大。

Because the concrete servers "FirstServer" and "SecondServer" implement the interface ClientServer they are dependent of that interface too. And because inheritance is a stronger dependency than the composition, the concrete server classes are more dependent of the interface than the Client class.

这就是为什么依赖性被反转的原因。现在,具体的服务器类取决于 Client-ClientServer集团。

That's why the dependencies are inverted. The concrete server classes now depend on the "Client-ClientServer"-conglomerate.

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

So the answer to your question is: You can't reach DIP when you create your class inside another class. But you can reach DIP with composition by defining an interface an injecting the concrete classes which inherit this interface.

这篇关于依赖倒置的原理和组成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆