Dependency Injection

Imagine we are going to develop an email composition system. We will use this system to compose and send the email. These are tasks we need to do:

  • Writing the message
  • Checking spelling
  • Looking up a recipient’s address
  • Send the email

We have the below objects responsible for doing these tasks:

  • TextEditor for writing the message
  • SpellChecker for checking spelling
  • AddressBook for recipient’s address
  • Emailer is responsible for sending the email

In this example, we can see Emailer depends on a TextEditor, a SpellChecker and an AddressBook to send the email. This relationship is called dependency. Here Emailer is a client of its dependencies – an object depends on the other objects. This is also called object graph.

Few more things to note here:

  • Service – An object that performs a well-defined function when called upon
  • Client – Any consumer of a service, an object that calls upon a service to perform a well-understood function.

They are also referred as dependency and dependent respectively. A client cannot function without its services. In other words, an object cannot function properly without its dependencies.

Let’s see how we can build the object graph without Dependency Injection.

public class Emailer {
   private SpellChecker spellChecker;
   
   public Emailer() {
      this.spellChecker = new SpellChecker();
   }
   
   public void send(String text) { .. }
}

Creating an Emailer with a SpellChecker is simple

Emailer myEmailer = new Emailer();

Now say we want to have spell checkers in different languages. This is certainly not possible with the above code because here Emailer encapsulates the creation of its dependencies. Moreover the above code is not testable because we cannot replace the internal spell checker that Emailer has with a dummy one.

Let’s improve this

public class Emailer {
   private SpellChecker spellChecker;
   public void setSpellChecker(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }
   ...
   ...
}

In this code we have a method that accepts a SpellChecker. Now we can use different spell checkers in our Emailer. Let’s try a French spell checker:

Emailer myEmailer = new Emailer();
myEmailer.setSpellChecker(new FrenchSpellChecker());

What about a Japanese one:

Emailer myEmailer = new Emailer();
myEmailer.setSpellChecker(new JapaneseSpellChecker());

Now we can test it with a mock spell checker

Emailer myEmailer = new Emailer();
myEmailer.setSpellChecker(new MockSpellChecker());

This gives us the option to pick a suitable spell checker service (English, French, or Japanese) that suits our need. We could have done this with a constructor.

public class Emailer {
  private SpellChecker spellChecker;
  public Emailer(SpellChecker spellChecker) {
     this.spellChecker = spellChecker;
  }
  ...
  ...
}
Emailer myEmailer = new Emailer(new EnglishSpellChecker());

Here we are constructing the object graph ourselves, construction by hand. Though this is better than the previous one, still tedious. If we use the same object in many places, we must repeat the code for wiring objects in all of those places. Not only this if we want to alter the dependency graph or any of its parts, we may be forced to go through and alter all of its client as well. Another problem is that users need to know how object graphs are wired internally.

We can remove this concrete dependency by creating the dependency externally and inject into Emailer. The task of creating, assembling, and wiring the dependencies into an object graph is performed by an external framework (or library) known as a dependency injection framework or simply a Dependency Injection (DI).

Control over the construction, wiring, and assembly of an object graph no longer resides with the clients or services themselves.

Example of DI frameworks: Spring, PicoContainer, Guice.

Here is an example how we can do this using Spring

public class Emailer {
   private SpellChecker spellChecker;
   private AddressBook addressBook;

   public void setSpellChecker(SpellChecker spellChecker){
      this.spellChecker = spellChecker;
   }
   
   public void setAddressBook(AddressBook addressBook){
      this.addressBook = addressBook;
   }

   public void send(String text) {
     ...
   }
}
<beans xmlns=”http://www.springframework.org/schema/beans”
       xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
       xsi:schemaLocation=”http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd”>

       <bean id=”spellChecker” class=”com.roytech.EnglishSpellChecker” />

       <bean id=”addressBook” class=”com.roytech.OfficeAddressBook” />

       <bean id=”emailer” class=”com.roytech.Emailer">
                <property name="spellChecker" ref="spellChecker”/>
                <property name="addressBook" ref="addressBook"/>
        </bean>                                                                                                           
</beans>
Advertisements
Dependency Injection

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s