Browser docs

Dependency Injection

Intent

Dependency Injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object (or client) and are made part of the client’s state. The pattern separates the creation of a client’s dependencies from its own behavior, which allows program designs to be loosely coupled and to follow the inversion of control and single responsibility principles.

Explanation

Real world example

The old wizard likes to fill his pipe and smoke tobacco once in a while. However, he doesn’t want to depend on a single tobacco brand only but likes to be able to enjoy them all interchangeably.

In plain words

Dependency Injection separates creation of client’s dependencies from its own behavior.

Wikipedia says

In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies.

Programmatic Example

Let’s first introduce the Tobacco interface and the concrete brands.

 1@Slf4j
 2public abstract class Tobacco {
 3
 4  public void smoke(Wizard wizard) {
 5    LOGGER.info("{} smoking {}", wizard.getClass().getSimpleName(),
 6        this.getClass().getSimpleName());
 7  }
 8}
 9
10public class SecondBreakfastTobacco extends Tobacco {
11}
12
13public class RivendellTobacco extends Tobacco {
14}
15
16public class OldTobyTobacco extends Tobacco {
17}

Next here’s the Wizard class hierarchy.

 1public interface Wizard {
 2
 3  void smoke();
 4}
 5
 6public class AdvancedWizard implements Wizard {
 7
 8  private final Tobacco tobacco;
 9
10  public AdvancedWizard(Tobacco tobacco) {
11    this.tobacco = tobacco;
12  }
13
14  @Override
15  public void smoke() {
16    tobacco.smoke(this);
17  }
18}

And lastly we can show how easy it is to give the old wizard any brand of tobacco.

1    var advancedWizard = new AdvancedWizard(new SecondBreakfastTobacco());
2    advancedWizard.smoke();

Class diagram

alt text

Applicability

Use the Dependency Injection pattern when:

  • When you need to remove knowledge of concrete implementation from object.
  • To enable unit testing of classes in isolation using mock objects or stubs.

Credits