102 lines
3.2 KiB
Markdown
102 lines
3.2 KiB
Markdown
|
---
|
||
|
layout: pattern
|
||
|
title: Dependency Injection
|
||
|
folder: dependency-injection
|
||
|
permalink: /patterns/dependency-injection/
|
||
|
categories: Creational
|
||
|
tags:
|
||
|
- Decoupling
|
||
|
---
|
||
|
|
||
|
## 目的
|
||
|
|
||
|
依赖注入是一种软件设计模式,其中一个或多个依赖项(或服务)被注入或通过引用传递到一个依赖对象(或客户端)中,并成为客户端状态的一部分。该模式将客户的依赖关系的创建与其自身的行为分开,这使程序设计可以松散耦合,并遵循控制反转和单一职责原则。
|
||
|
|
||
|
## 解释
|
||
|
|
||
|
真实世界例子
|
||
|
|
||
|
> 老巫师喜欢不时地装满烟斗抽烟。 但是,他不想只依赖一个烟草品牌,而是希望能够互换使用它们。
|
||
|
|
||
|
通俗的说
|
||
|
|
||
|
> 依赖注入将客户端依赖的创建与其自身行为分开。
|
||
|
|
||
|
维基百科说
|
||
|
|
||
|
> 在软件工程中,依赖注入是一种对象接收其依赖的其他对象的技术。 这些其他对象称为依赖项。
|
||
|
|
||
|
**程序示例**
|
||
|
|
||
|
先介绍一下烟草接口和具体的品牌。
|
||
|
|
||
|
```java
|
||
|
public abstract class Tobacco {
|
||
|
|
||
|
private static final Logger LOGGER = LoggerFactory.getLogger(Tobacco.class);
|
||
|
|
||
|
public void smoke(Wizard wizard) {
|
||
|
LOGGER.info("{} smoking {}", wizard.getClass().getSimpleName(),
|
||
|
this.getClass().getSimpleName());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public class SecondBreakfastTobacco extends Tobacco {
|
||
|
}
|
||
|
|
||
|
public class RivendellTobacco extends Tobacco {
|
||
|
}
|
||
|
|
||
|
public class OldTobyTobacco extends Tobacco {
|
||
|
}
|
||
|
```
|
||
|
|
||
|
下面是老巫师的类的层次结构。
|
||
|
|
||
|
```java
|
||
|
public interface Wizard {
|
||
|
|
||
|
void smoke();
|
||
|
}
|
||
|
|
||
|
public class AdvancedWizard implements Wizard {
|
||
|
|
||
|
private final Tobacco tobacco;
|
||
|
|
||
|
public AdvancedWizard(Tobacco tobacco) {
|
||
|
this.tobacco = tobacco;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void smoke() {
|
||
|
tobacco.smoke(this);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
最后我们可以看到给老巫师任意品牌的烟草是多么的简单。
|
||
|
|
||
|
```java
|
||
|
var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());
|
||
|
advancedWizard.smoke();
|
||
|
```
|
||
|
|
||
|
## 类图
|
||
|
|
||
|

|
||
|
|
||
|
## 适用性
|
||
|
|
||
|
使用依赖注入当:
|
||
|
|
||
|
- 当你需要从对象中移除掉具体的实现内容时
|
||
|
|
||
|
* 使用模拟对象或存根隔离地启用类的单元测试
|
||
|
|
||
|
## 鸣谢
|
||
|
|
||
|
* [Dependency Injection Principles, Practices, and Patterns](https://www.amazon.com/gp/product/161729473X/ref=as_li_qf_asin_il_tl?ie=UTF8&tag=javadesignpat-20&creative=9325&linkCode=as2&creativeASIN=161729473X&linkId=57079257a5c7d33755493802f3b884bd)
|
||
|
* [Clean Code: A Handbook of Agile Software Craftsmanship](https://www.amazon.com/gp/product/0132350882/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0132350882&linkCode=as2&tag=javadesignpat-20&linkId=2c390d89cc9e61c01b9e7005c7842871)
|
||
|
* [Java 9 Dependency Injection: Write loosely coupled code with Spring 5 and Guice](https://www.amazon.com/gp/product/1788296257/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=1788296257&linkId=4e9137a3bf722a8b5b156cce1eec0fc1)
|
||
|
* [Google Guice Tutorial: Open source Java based dependency injection framework](https://www.amazon.com/gp/product/B083P7DZ8M/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=B083P7DZ8M&linkId=04f0f902c877921e45215b624a124bfe)
|