依赖倒置原理及组成
Dependency inversion principle and composition
我正在阅读 SOLID 原则,我在“依赖倒置原则” 上停下来,这意味着对象应该已经实例化到另一个对象,这意味着 composition 不能应用 依赖倒置原则 对吗?或者有什么我想念的?
更新 ************************************************* *
假设你有一个 class 并且这个 class 有一个引用另一个对象的属性,我们有 2 个解决方案(对我来说):
- 在 class 之外创建对象并将其传递给 class。(依赖)
- 在 class 内部创建对象 it self(composition)。
谢谢。
已拍摄 from Wikipedia:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
你说:
which means the objects should passed already instantiated to another object
Dependency Inversion 原则与 class 构造函数 等编程实现细节无关,它们旨在初始化对象正在建设中。
除非您将构造函数参数定义为实现而不是抽象,and/or被注入的依赖项比目标依赖项处于更高层,否则您不是违反了整个原则。
你的困惑来自于你对构图的理解。另一个人拥有的对象取决于拥有对象的生命周期。这并不意味着您必须在拥有 class.
内创建拥有的对象
如果您在 class 中创建对象,则此 class 与创建的 class 紧密耦合。您不能在不更改创建另一个的 class 的情况下交换实现。
示例:
在上图中,您有 class 客户端,它使用 class 服务器。可以说这是一个组合,客户端具有服务器类型的属性。
如果您在客户端 class 中创建 class 服务器的实例,它可能如下所示:
public class Client {
private Server server;
public Client(){
this.server = new Server();
}
}
现在假设您要交换服务器的实现。您需要更改客户端 class 的实现,因为交换它的唯一方法是创建另一个 class(可能称为 AnotherServer)的实例。
public class Client {
private AnotherServer anotherServer;
public Client(){
this.anotherServer = new AnotherServer();
}
}
这表明客户端 class 高度依赖于 class 服务器。
要轻松更改服务器的使用实现,从而修改客户端的行为,最好从抽象(抽象 classes 或接口)中组合客户端。这样做意味着您无法在拥有 class 中创建所需的对象,因为您只能创建具体的 classes。创建 classes 意味着调用构造函数并依赖于所创建的 class。
实现组合的更好方法(– 客户端由服务器组成 –)是通过 setter 方法或构造函数注入它。像这样,您可以将实现 class 隐藏在接口后面。
示例:
在第二张图片中,我们保护客户端不了解服务器的具体实现。它仅取决于服务器接口。这种依赖性并不那么显着,因为客户端定义了接口。他决定服务器接口所需的功能。为了表明服务器的接口属于客户端,它被称为 "ClientServer".
要编写您的客户端,您必须在 class 之外为 ClientServer 接口创建具体的 classes,并通过构造函数或 setter 方法注入它。
...
FirstServer first = new FirstServer();
Client client = new Client(first);
client.setServer(new SecondServer());
...
像这样您可以轻松地在客户端中交换使用过的服务器实现,甚至在运行时也是如此。
这种机制称为依赖倒置原则(DIP)。但为什么?客户端 class 仍然依赖于服务器接口。如果界面改变了,客户端也必须改变。是的,这是正确的。但是客户决定他在该界面中需要哪些功能。所以通常界面会改变,当客户说它需要改变时。界面变了,因为客户端变了。
因为具体服务器 "FirstServer" 和 "SecondServer" 实现接口 ClientServer 它们也依赖于该接口。并且因为继承是比组合更强的依赖性,所以具体服务器 classes 比客户端 class.
更依赖于接口。
这就是依赖关系颠倒的原因。具体服务器 classes 现在依赖于 "Client-ClientServer"-conglomerate。
所以你的问题的答案是:当你在另一个 class 中创建你的 class 时,你无法到达 DIP。但是您可以通过定义一个接口并注入继承该接口的具体 classes 来实现组合 DIP。
我正在阅读 SOLID 原则,我在“依赖倒置原则” 上停下来,这意味着对象应该已经实例化到另一个对象,这意味着 composition 不能应用 依赖倒置原则 对吗?或者有什么我想念的? 更新 ************************************************* * 假设你有一个 class 并且这个 class 有一个引用另一个对象的属性,我们有 2 个解决方案(对我来说):
- 在 class 之外创建对象并将其传递给 class。(依赖)
- 在 class 内部创建对象 it self(composition)。
谢谢。
已拍摄 from Wikipedia:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.
你说:
which means the objects should passed already instantiated to another object
Dependency Inversion 原则与 class 构造函数 等编程实现细节无关,它们旨在初始化对象正在建设中。
除非您将构造函数参数定义为实现而不是抽象,and/or被注入的依赖项比目标依赖项处于更高层,否则您不是违反了整个原则。
你的困惑来自于你对构图的理解。另一个人拥有的对象取决于拥有对象的生命周期。这并不意味着您必须在拥有 class.
内创建拥有的对象如果您在 class 中创建对象,则此 class 与创建的 class 紧密耦合。您不能在不更改创建另一个的 class 的情况下交换实现。
示例:
在上图中,您有 class 客户端,它使用 class 服务器。可以说这是一个组合,客户端具有服务器类型的属性。
如果您在客户端 class 中创建 class 服务器的实例,它可能如下所示:
public class Client {
private Server server;
public Client(){
this.server = new Server();
}
}
现在假设您要交换服务器的实现。您需要更改客户端 class 的实现,因为交换它的唯一方法是创建另一个 class(可能称为 AnotherServer)的实例。
public class Client {
private AnotherServer anotherServer;
public Client(){
this.anotherServer = new AnotherServer();
}
}
这表明客户端 class 高度依赖于 class 服务器。
要轻松更改服务器的使用实现,从而修改客户端的行为,最好从抽象(抽象 classes 或接口)中组合客户端。这样做意味着您无法在拥有 class 中创建所需的对象,因为您只能创建具体的 classes。创建 classes 意味着调用构造函数并依赖于所创建的 class。
实现组合的更好方法(– 客户端由服务器组成 –)是通过 setter 方法或构造函数注入它。像这样,您可以将实现 class 隐藏在接口后面。
示例:
在第二张图片中,我们保护客户端不了解服务器的具体实现。它仅取决于服务器接口。这种依赖性并不那么显着,因为客户端定义了接口。他决定服务器接口所需的功能。为了表明服务器的接口属于客户端,它被称为 "ClientServer".
要编写您的客户端,您必须在 class 之外为 ClientServer 接口创建具体的 classes,并通过构造函数或 setter 方法注入它。
...
FirstServer first = new FirstServer();
Client client = new Client(first);
client.setServer(new SecondServer());
...
像这样您可以轻松地在客户端中交换使用过的服务器实现,甚至在运行时也是如此。
这种机制称为依赖倒置原则(DIP)。但为什么?客户端 class 仍然依赖于服务器接口。如果界面改变了,客户端也必须改变。是的,这是正确的。但是客户决定他在该界面中需要哪些功能。所以通常界面会改变,当客户说它需要改变时。界面变了,因为客户端变了。
因为具体服务器 "FirstServer" 和 "SecondServer" 实现接口 ClientServer 它们也依赖于该接口。并且因为继承是比组合更强的依赖性,所以具体服务器 classes 比客户端 class.
更依赖于接口。这就是依赖关系颠倒的原因。具体服务器 classes 现在依赖于 "Client-ClientServer"-conglomerate。
所以你的问题的答案是:当你在另一个 class 中创建你的 class 时,你无法到达 DIP。但是您可以通过定义一个接口并注入继承该接口的具体 classes 来实现组合 DIP。