面向对象编程的 SOLID 原则 - 依赖倒置原则 - DIP
依赖倒置原则
依赖倒置原则描述的是我们的 class 应该依赖接口和抽象类而不是具体的类和函数。
在这篇文章(2000)里,Bob 大叔如下总结该原则:
“如果 OCP 声明了 OO 体系结构的目标,那么 DIP 则声明了主要机制”。
这两个原则的确息息相关,我们在讨论开闭原则之前也要用到这一模式。
我们想要我们的类开放扩展,因此我们需要明确我们的依赖的是接口而不是具体的类。我们的 PersistenceManager class 依赖 InvoicePersistence 而不是实现了这个接口的 class。
highlevel 实体中得到low-level实体
问题: PoductCatalog should not warry about instantiation of its dependency
那么如何依赖初始化呢?
// high
PoductCatalog {
public func listAllPoducts() {
PoductRepository productRepository = ProductFactory.create()
list <string> allProductNames = productRepository.getAllPoductNames();
}
}
public class ProductFactory {
public static PoductRepository create () {
return new SqlProductRepository();
}
}
// abstraction
ProductRepository {
public list <string> getAllPoductNames()
}
// low
SqlProductRepository implements ProductRepository {
public list <string> getAllPoductNames{
// get data from database
return list
}
}
DI(dependecy injection)
now when ProductCatalog is created , it gets a sqlProductRepository object
we inject dendency INTO (DI)
// 修改PoductCatalog
PoductCatalog {
// interface obj
private ProductRepository productRepository;
public ProductCatalog(ProductRepository productRepository) {
this.prductRepository = productRepository;
}
public func listAllPoducts() {
list <string> allProductNames = productRepository.getAllPoductNames();
}
}
public class EcommerceMainApplication {
public static void main(string [] args) {
ProductRepository productRepository = productFactory.create();
ProductCatalog productCatalog = new ProductCatalog(productRepository)
productCatolog.ListAllProducts();
}
}
扩展:IOC和DI
控制反转(IOC)和依赖注入(DI)是Spring中最重要的核心概念之一,而两者实际上是一体两面的。
- 依赖注入
- 一个类依赖另一个类的功能,那么就通过注入,如构造器、setter方法等,将这个类的实例引入。
- 侧重于实现。
- 控制反转
- 创建实例的控制权由一个实例的代码剥离到IOC容器控制,如xml配置中。
- 侧重于原理。
- 反转了什么:原先是由类本身去创建另一个类,控制反转后变成了被动等待这个类的注入。