前言
dagger2 是目前由Google维护的一个依赖注入的框架。也是火的一塌糊涂。目前笔者也正着手学习和使用在实际项目中。说到依赖注入,网上很多文章都是从一个小小的案例两个类的依赖关系进行推演,说到依赖注入就是为了更好的解耦。但是,并没有具体讲为什么要这样解耦,笔者就想深究一下。其实也不是什么高深的东西,依赖注入说到底就是写代码的一种套路,那么为什么有这种套路呢,所谓套路其实就是大家常说的设计模式来或者面向对象啦此类的。不知读者读到这里有没有灵光一闪。
依赖倒置原则
面向对象的六大原则之一,英文翻译 Dependence Inversion Principle ,一种特定的解耦形式,高层模块不依赖于低层模块的实现的细节,依赖模块被颠倒了,可能有点难理解。
依赖倒置原则遵循以下几个关键点:
1 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
2 抽象不应该依赖细节
3 细节应该依赖抽象;
在java中,抽象就指 抽象类和接口类,不能被实例化的,细节就是这两者的继承类和实现类,其特点就是可以被实例化,就是说可以new出来一个他的实例。高层模块是调用端,低层模块就是实现类。依赖倒置在java中就是:<b>模块之间依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的。</b>其实说白了大白话,就是面向接口编程,面向抽象编程。面向接口编程是面向对象理论的精髓之一。所以依赖倒置过程中的解耦形式,就是调用代码中,都是用的接口类型的对象实例,调用端无需知道,具体谁实现的这个接口,从而实现解耦,在运行和测试环境下,当传入不同的实现类可以完成不同的工作。
依赖注入
通过上面的背景了解,我们知道:所谓 依赖注入 依赖就是调用端里面的接口对象,或者说这些对象就是高层调用端的依赖。如下:
下面看一小段代码
public class Car{
private Engine engine;
public Car(){
engine = new Engine();
}
}
这段Java代码中Car类持有了对Engine实例的引用,我们称之为Car类对Engine类有一个依赖。由于没有依赖注入,因此需要我们自己是在Car的构造函数中创建Engine对象。
这样明显丧失了灵活性,一切依赖都是在Car类的内部创建,Car与Engine严重耦合。一旦Engine创建方式发生了改变,我们就必须要去修改Car类的构造函数另外我们也没办法替换动态的替换依赖实例(比如我们想把Engine的品牌更换 或者更换型号)。这类问题在大型的商业项目中则更加严重,往往A依赖B、B依赖C、C依赖D、D依赖E;一旦稍有改动便牵一发而动全身,想想都可怕!而依赖注入则很好的帮我们解决了这一问题。且看下面的代码
依赖注入其实并不神奇,我们日常的代码中很多都用到了依赖注入,但很少注意到它,也很少主动使用依赖注入进行解耦。这里我们简单介绍一下赖注入实现三种的方式。
1 构造注入
public class Car{
private Engine engine;
public Car(Engine engine){
this.engine = engine;
}
}
2 接口注入 常见于mvp模式中
public interface Injection<T>{
void inject(T t);
}
public class Car implements Injection<Engine>{
private Engine engine;
public Car(){}
public void inject(Engine engine){
this.engine = engine;
}
}
3 set方法注入
public class Car {
private Engine engine;
public Car(){}
public void setEngine(Engine engine){
this.engine = engine;
}
}
4 注解注入
public class Car{
@Inject
Engine engine;
public Car(){}
}
这四段代码都达到了解耦的目的,达到高内聚低耦合的目的,保证代码的健壮性、灵活性和可维护性。(依赖的实例化不在Car类内部,就是不在这里new出来的),
至此,所有的依赖注入功能及展示形式,是不是很简单!!他是如何解耦的稍微回味一下,很好理解。今天就到这,对我自己说晚安!
文章索引
dagger2 循序渐进学习(一)依赖注入基础知识(包会)
dagger2 循序渐进学习(二)
dagger2 循序渐进学习(三) 实例1,application中的应用