依赖反转原则
提出问题
- 依赖反转这个概念指的是"谁跟谁"的"什么依赖"被反转了?”反转“两个字该如何理解?
- "控制反转"和"依赖注入"这两个概念和依赖反转有什么区别和联系?
- 如果你熟悉Java语言,那Spring框架中的IOC跟这些概念又有什么关系呢?
控制反转(IOC)
Inversion Of Control
如何理解
控制:指的是程序对执行流程的控制
反转:指的是在没有使用框架之前,程序员自己控制整个程序的执行。在使用框架之后,整个程序的执行流程可以通过框架来控制。流程的控制权从程序员"反转"到了框架。
注:控制反转并不是一种具体的实现技巧,而是一个比较笼统的设计思想,一般用来指导框架层面的设计。
应用示例
/**
* 测试用例基类
*/
public abstract class TestCase{
public void run(){
if(doTest()){
System.out.println("Test successed.");
}else{
System.out.println("Test failed.");
}
}
public abstract void doTest();
}
public class JunitApplication{
private static final List<TestCase> testCases=new ArrayList<>();
public static void register(TestCase testCase){
testCases.add(testCase);
}
public static void main(String[] args){
for(TestCase testCase:testCases){
case.run();
}
}
}
分析:以上代码中测试用例的流程由 main方法中for循环执行,程序员只需要实现基类TestCase中的doTest方法,而不需要关系执行流程。
## 依赖注入(DI)
Dependency Injection
不通过new()的方式在类内部创建依赖类对象,而是将依赖的对象在外部创建好之后,通过构造函数、函数参数等方式传递(或注入)给类使用。
注:依赖注入是一种具体的编码技巧。
应用示例
/**
* 非依赖注入方式实现
*/
public class Notification{
private MessageSender messageSender;
public Notification(){
this.messanger=new MessageSender();//此处是new方式创建对象
}
}
/**
* 依赖注入方式实现
*/
public class Notification{
private MessageSender messageSender;
public Notification(){
}
//构造函数注入方式
public Notification(MessageSender messageSender){
this.messageSender=messageSender;
}
}
依赖注入框架(DI Framework)
产生原因
由于项目中可能会涉及很多类,类和对象的创建和依赖注入会变得非常复杂。如果这部分工作全靠程序员自己写代码完成,容易出错且开发成本也比较高。而对象创建和依赖注入的工作,本身跟具体的业务无关,完全可以抽象成框架来自动完成。
框架作用
通过依赖注入框架可以通过简单的配置一下类和类之间的依赖关系,就可以由框架自动创建对象、管理对象的声明周期、依赖注入等原本需要程序员来做的事情。
## 控制反转原则
Dependency Inversion Principle (DIP) 依赖反转原则
如何理解
High-level modules shouldn
t depend on low-level modules. Both modules shoud depend on abstractions. In addition, abstractions shouldn
t depend on details. Details depend on abstractions.
高层模块(high-level modules)不要依赖低层模块(low-level)。高层模块和低层模块应该通过抽象来相互依赖。除此之外,抽象(abstractions) 不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions)。
高层模块:在调用链上,调用者属于高层
底层模块:在调用链上,被调用者属于低层
注:本文是根据尚硅谷和极客学院的课程整理的学习笔记,如要深入理解,请收看老师的原版视频。