什么是依赖倒置原则?为什么它很重要?
当前回答
控制反转(IoC)是一种设计模式,在这种模式下,对象通过外部框架获得其依赖项,而不是向框架请求其依赖项。
使用传统查找的伪代码示例:
class Service {
Database database;
init() {
database = FrameworkSingleton.getService("database");
}
}
使用IoC的类似代码:
class Service {
Database database;
init(database) {
this.database = database;
}
}
国际奥委会的好处是:
您不依赖于中心 框架,所以这可以改变如果 想要的。 因为对象是被创建的 以注射方式使用为佳 接口,很容易创建单元 替换依赖项的测试 模拟版本。 解耦代码。
其他回答
依赖倒置的重点是制作可重用的软件。
其思想是,两段代码不再相互依赖,而是依赖于一些抽象的接口。然后你可以在没有另一块的情况下重复使用其中的任何一块。
最常见的实现方式是通过控制反转(IoC)容器,如Java中的Spring。在这个模型中,对象的属性是通过XML配置来设置的,而不是由对象自己去寻找它们的依赖项。
想象一下这个伪代码……
public class MyClass
{
public Service myService = ServiceLocator.service;
}
MyClass直接依赖于Service类和ServiceLocator类。如果你想在另一个应用程序中使用它,这两个都需要。现在想象一下……
public class MyClass
{
public IService myService;
}
现在,MyClass依赖于一个单独的接口,IService接口。我们让IoC容器实际设置那个变量的值。
所以现在,MyClass可以很容易地在其他项目中重用,而不会带来其他两个类的依赖关系。
更好的是,您不必拖动MyService的依赖项,以及这些依赖项的依赖项,以及…好吧,你懂的。
我可以在上面的回答中看到很好的解释。然而,我想用简单的例子提供一些简单的解释。
依赖倒置原则允许程序员删除硬编码的依赖项,这样应用程序就变得松散耦合和可扩展。
如何实现这一点:通过抽象
没有依赖反转:
class Student {
private Address address;
public Student() {
this.address = new Address();
}
}
class Address{
private String perminentAddress;
private String currentAdrress;
public Address() {
}
}
在上面的代码片段中,地址对象是硬编码的。相反,如果我们可以使用依赖倒置,并通过传递构造函数或setter方法注入地址对象。让我们来看看。
使用依赖倒置:
class Student{
private Address address;
public Student(Address address) {
this.address = address;
}
//or
public void setAddress(Address address) {
this.address = address;
}
}
依赖倒置:依赖抽象,而不是具体。
控制反转:主要与抽象,以及主要如何成为系统的粘合剂。
以下是一些关于这方面的好文章:
https://coderstower.com/2019/03/26/dependency-inversion-why-you-shouldnt-avoid-it/
https://coderstower.com/2019/04/02/main-and-abstraction-the-decoupled-peers/
https://coderstower.com/2019/04/09/inversion-of-control-putting-all-together/
基本上它说:
类应该依赖于抽象(例如接口,抽象类),而不是特定的细节(实现)。
依赖倒置原理(DIP)
它是SOLID[About]的一部分,SOLID[About]是OOD的一部分,由Bob叔叔介绍。它是关于类(层…)之间的松散耦合。类不应该依赖于具体的实现,类应该依赖于抽象/接口
问题:
//A -> B
class A {
B b
func foo() {
b = B();
}
}
解决方案:
//A -> IB <|- B
//client[A -> IB] <|- B is the Inversion
class A {
IB ib // An abstraction between High level module A and low level module B
func foo() {
ib = B()
}
}
现在A不依赖于B(一对一),现在A依赖于B实现的接口IB,这意味着A依赖于IB的多重实现(一对多)
[DIP vs DI vs IoC]