--- 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(); ``` ## 类图 ![alt text](../../dependency-injection/etc/dependency-injection.png "Dependency Injection") ## 适用性 使用依赖注入当: - 当你需要从对象中移除掉具体的实现内容时 * 使用模拟对象或存根隔离地启用类的单元测试 ## 鸣谢 * [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)