Understanding Dependency Injection and its Importance, A tutorial

Understanding Dependency Injection and its Importance

Any application is composed of many objects that collaborate with each other to perform some useful stuff. Traditionally each object is responsible for obtaining its own references to the dependent objects (dependencies) it collaborate with. This leads to highly coupled classes and hard-to-test code.

For example, consider a `Car` object.

A `Car` depends on wheels, engine, fuel, battery, etc. to run. Traditionally we define the brand of such dependent objects along with the definition of the `Car` object.

Without Dependency Injection (DI):

  class Car{  
    private Wheel wh = new NepaliRubberWheel();  
    private Battery bt = new ExcideBattery();  
    //The rest  
   }  

Here, the `Car` object *is responsible for creating the dependent objects.*

What if we want to change the type of its dependent object - say `Wheel` - after the initial `NepaliRubberWheel()` punctures?
We need to recreate the Car object with its new dependency say `ChineseRubberWheel()`, but only the `Car` manufacturer can do that.

 Then what does the `Dependency Injection` do for us...?


When using dependency injection, objects are given their dependencies *at run time rather than compile time (car manufacturing time)*.
So that we can now change the `Wheel` whenever we want. Here, the `dependency` (`wheel`) can be injected into `Car` at run time.

After using dependency injection:

Here, we are **injecting** the **dependencies** (Wheel and Battery) at runtime. Hence the term : *Dependency Injection.* We normally rely on DI frameworks such as Spring, Guice, Weld to create the dependencies and inject where needed.

   class Car{  
    private Wheel wh; // Inject an Instance of Wheel (dependency of car) at runtime  
    private Battery bt; // Inject an Instance of Battery (dependency of car) at runtime  
    Car(Wheel wh,Battery bt) {  
      this.wh = wh;  
      this.bt = bt;  
    }  
    //Or we can have setters  
    void setWheel(Wheel wh) {  
      this.wh = wh;  
    }  
   }  

The advantages/benefits of dependency injection are:

  • decoupling the creation of an object (in another word, separate usage from the creation of object)
  • ability to replace dependencies (eg: Wheel, Battery) without changing the class that uses it(Car)
  • promotes "Code to interface not to an implementation" principle
  • ability to create and use mock dependency during a test (if we want to use a Mock of Wheel during test instead of a real instance.. we can create Mock Wheel object and let DI framework inject to Car)

6 comments :

  1. Good presentation, but I am not sure I want loose coupling of wheels to my car... Not on the road, at least! ;-)

    ReplyDelete
  2. Hi could you show how the code would look like after DI? as in the instantiation would come in the constructor is it?

    ReplyDelete
    Replies
    1. Please take a look at this :
      http://ganeshtiwaridotcomdotnp.blogspot.com/2011/05/dependency-injection-with-java-spring.html

      Delete
  3. I got confused. Then what is the difference between factory design pattern and dependency injection. In factory also, we create objects at run time.

    ReplyDelete
    Replies
    1. DI focuses on creating and injecting the dependencies. Composition(factory pattern and others) requires the developer to create the objects and pass it.

      Delete

Your Comment and Question will help to make this blog better...