Design Pattern - Dependency Injection

> Code - (Programming|Computer) Language > Design Pattern

1 - About

Dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle.

An injection is the passing of a dependency (a service) to a dependent object (a client). The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

The term is related to but different from the dependency inversion principle, which concerns itself with decoupling dependencies between high-level and low-level layers through shared abstractions.

Basically, instead of having your objects creating a dependency or asking a factory object to make one for them, you pass the needed dependencies in to the constructor or via property setters, and you make it somebody else's problem (an object further up the dependency graph, or a dependency injector that builds the dependency graph). A dependency as I'm using it here is any other object the current object needs to hold a reference to.

(inject|invoke)

For instance, you can inject a bean into a Servlet by using this annotation.

@EJB myBean ejb;
Advertising

3 - Purpose

The purpose of Dependency Injection is to reduce coupling in your application to make it more flexible and easier to test, ensure that components are loosely coupled.

4 - Benefits

Objects don't have hard coded dependencies. If you need to change the implementation of a dependency, all you have to do is Inject a different type of Object.

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 dependency inversion and single responsibility principles. It directly contrasts the service locator pattern, which allows clients to know about the system they use to find dependencies

5 - Implementation

Usually a container manages the lifecycle of objects and their dependencies based on a configuration file or annotations.

It allows to resolve dependencies at run time using containers such as Windsor Castle, Unity, Spring.net, MEF which allows applications to be extensible.

Dependency injection involves four elements:

  • the implementation of a service object;
  • the client object depending on the service;
  • the interface the client uses to communicate with the service;
  • and the injector object, which is responsible for injecting the service into the client. The injector object may also be referred to as an assembler, provider, container, factory, or spring

6 - Injection Example

How an object can receive a reference to an external module:

  • constructor injection: the dependencies are provided through a class constructor.
  • setter injection: the client exposes a setter method that the injector uses to inject the dependency.
  • interface injection: the dependency provides an injector method that will inject the dependency into any client passed to it. Clients must implement an interface that exposes a setter method that accepts the dependency.
Advertising

6.1 - Without Injection

  • An example without dependency injection
public class Client {
 
    // Internal reference to the service used by this client
    private Service service;
 
    // Constructor
    Client() {
        // Specify a specific implementation in the constructor instead of using dependency injection
        service = new ServiceExample();
    }
 
    // Method within this client that uses the services
    public String greet() {
        return "Hello " + service.getName();
    }
}

6.2 - With constructor Injection

  • An example without dependency injection
public class Client {
 
    // Internal reference to the service used by this client
    private Service service;
 
    // Constructor
    Client(Service service) {
        // The service is given through a constructor argument
        this,service = service;
    }
 
    // Method within this client that uses the services
    public String greet() {
        return "Hello " + service.getName();
    }
}

6.3 - With setter injection

This method requires the client to provide a setter method for the dependency.

public class Client {
 
    // Internal reference to the service used by this client
    private Service service;
 
    // Constructor
    Client() {
    }
 
    // Setter method
    public void setService(Service service) {
        // Save the reference to the passed-in service inside this client
        this.service = service;
    }
 
    // Method within this client that uses the services
    public String greet() {
        return "Hello " + service.getName();
    }
}

6.4 - Interface injection

The interface define just how the injector should talk to the client when injecting dependencies.

  • Service setter interface.
public interface ServiceSetter {
    public void setService(Service service);
}
  • Client class
public class Client implements ServiceSetter {
    // Internal reference to the service used by this client.
    private Service service;
 
    // Set the service that this client is to use.
    @Override
    public void setService(Service service) {
        this.service = service;
    }
}
Advertising

7 - Documentation / Reference

code/design_pattern/injection.txt · Last modified: 2017/09/20 22:43 by 172.68.174.50