依赖倒置
6 大设计原则之一
原则
1.上层模块不应该依赖底层模块,它们都应该依赖于抽象。
2.抽象不应该依赖于细节,细节应该依赖于抽象。
上下层
上层:业务层,要进行的操作,就是做什么
底层:逻辑层,数据层,实现细节,就是怎么做
人出门的例子
人出门的交通工具多种多样,Driver作为抽象类,人依赖于Driver,至于骑车还是坐车,都由Driver的实现类去处理,比如Bike,Car等,实现类就是细节
常规写法
public class Person {
private Bike mBike;
public Person() {
mBike = new Bike();
}
public void chumen() {
System.out.println("出门了");
mBike.drive();
}
}
增加接口
public class Person {
// private Bike mBike;
// private Car mCar;
// private Train mTrain;
private Driveable mDriveable;
public Person() {
mDriveable = new Train();
}
public void chumen() {
System.out.println("出门了");
//mBike.drive();
//mCar.drive();
//mTrain.drive();
mDriveable.drive();
}
}

依赖倒置实质上是面向接口编程的体现
控制反转(IoC)
控制反转 IoC 是 Inversion of Control的缩写,意思就是对于控制权的反转
刚才是Person自己实例化Driver,现在在构造函数里传入Driver,这样无论出行方式怎么变化,Person类都不用动
控制反转
public class Person {
private Driveable mDriveable;
public Person(Driveable driveable) {
this.mDriveable = driveable;
}
public void chumen() {
System.out.println("出门了");
mDriveable.drive();
}
}
public class Test1 {
public static void main(String[] args) {
Bike bike = new Bike();
Car car = new Car();
Train train = new Train();
// Person person = new Person(bike);
// Person person = new Person(car);
Person person = new Person(train);
person.chumen();
}
}
依赖注入(Dependency injection)
依赖注入,也经常被简称为 DI,其实在上一节中,我们已经见到了它的身影。它是一种实现 IoC 的手段。什么意思呢?
为了不因为依赖实现的变动而去修改 Person, 也就是说以可能在 Driveable 实现类的改变下不改动 Person 这个类的代码,尽可能减少两者之间的耦合。我们需要采用上一节介绍的 IoC 模式来进行改写代码.
这个需要我们移交出对于依赖实例化的控制权,那么依赖怎么办?Person 无法实例化依赖了,它就需要在外部(IoC 容器)赋值给它,这个赋值的动作有个专门的术语叫做注入(injection),需要注意的是在 IoC 概念中,这个注入依赖的地方被称为 IoC 容器,但在依赖注入概念中,一般被称为注射器 (injector)。
实现依赖注入有 3 种方式:
- 构造函数中注入
- setter 方式注入
- 接口注入
setter
public class Person {
public void setDriveable(Driveable mDriveable) {
this.mDriveable = mDriveable;
}
}
接口方式注入
public interface DepedencySetter {
void set(Driveable driveable);
}
class Person implements DepedencySetter{
private Driveable mDriveable;
@Override
public void set(Driveable driveable) {
this.mDriveable = mDriveable;
}
}
这种方式和 Setter 方式很相似。有很多同学可能有疑问那么加入一个接口是不是多此一举呢?
答案肯定是不是的,这涉及到一个角色的问题。还是以前面的餐厅为例,除了外卖员之外还有厨师和服务员,那么如果只有外卖员实现了一个送外卖的接口的话,那么餐厅配餐的时候就只会把外卖配置给外卖员。
接口的存在,表明了一种依赖配置的能力。
在软件框架中,读取 xml 配置文件,或者是利用反射技术读取注解,然后根据配置信息,框架动态将一些依赖配置给特定接口的类,我们也可以说 Injector 也依赖于接口,而不是特定的实现类,这样进一步提高了准确性与灵活性。
总结
1.依赖倒置是面向对象开发领域中的软件设计原则,它倡导上层模块不依赖于底层模块,抽象不依赖细节。
2.依赖反转是遵守依赖倒置这个原则而提出来的一种设计模式,它引入了 IoC 容器的概念。
3.依赖注入是为了实现依赖反转的一种手段之一。
4.它们的本质是为了代码更加的“高内聚,低耦合”。
1.控制反转是设计模式,遵从了依赖倒置原则
2.依赖注入是实现控制反转的手段