Introducing DI

DI is a software development technique where we can create objects that depend on other objects. DI helps the interaction between classes, but at the same time keeps the classes independent. 

There are three types of classes in DI:

  • A Service is a class that can be used (dependency).
  • The Client is a class that uses dependency.
  • The Injector passes the dependency (Service) to the dependent class (Client).

The three types of classes in DI are shown in the following diagram:

DI makes classes loosely coupled. This means that the creation of client dependencies is separated from the client's behavior, which makes unit testing easier.

Let's take a look at a simplified example of DI using Java code. In the following code, we don't have DI, because the client Car class is creating an object of the service class:

public class Car {
private Owner owner;

public Car() {
owner = new Owner();
}
}

In the following code, the service object is not directly created in the client class. It is passed as a parameter in the class constructor:

public class Car {
private Owner owner;

public Car(Owner owner) {
this.owner = owner;
}
}

The service class can also be some abstract class, then we can use any implementation of that in our client class and use mocks when testing.

There are different types of DI, for example, the following two types:

  • Constructor injection: Dependencies are passed to a client class constructor. An example of the constructor injection was already shown in the preceding Car example code. 
  • Setter injection: Dependencies are provided through setters. The following example code shows an example of the setter injection:
public class Car {
private Owner owner;

public void setOwner(Owner owner) {
this.owner = owner;
}
}