Saturday, May 23, 2009

Inversion of Control

What is IoC?

Inversion of Control, not surprisingly, is all about inverting the control. Or, how one object uses another object. Suppose class A wants to use class B. Traditionally, you would create and use an instance of class B within class A, like in the following example:
Class A {   
        private B b;
public A() {
b = new B();   
public void doSomething(){
You can easily spot the problems in creating dependency between two objects using this traditional approach:
  1. The creation of object B relies upon the availability of a default constructor.
  2. Any change in the constructor implementation of class B will necessitate achange in the implementation of class A.
  3. Suppose class A wants to use class C instead of class B. Then class A needs to change. What happens if class B and class C are two separate implementations of same service and the application will need to switch over from one implementation to the other?
All three ofthe problems in the code example are due the strong coupling of class A and class B. Class A first needs to know that it must use an instance of class B and then it needs to know how to construct an instance of class B.

The solution to this problem is to eliminate the dependency from class A. What follows is a modified class A, where strong coupling is removed:

Class A {    private B b;  public A(B b) {   this.b = b;     }      public void doSomething(){   b.someMethod();     } }
This example accepts an instance of class B via the constructor. This relieves class A from knowing how to instantiate class B. Now, in order to use class A, the caller class of A must also instantiate class B and pass it into class A. In this context, the caller class is also acting as an assembler of object A and object B. Object A does not explicitly look for B, but B is supplied to it. This is the Inversion of Control. The control of class B is taken out of class A and placed in the Assembler class.

There's Always Another Way: Dependency Lookup

UInstead of passing the reference of another object through the constructor, you can use Java Bean properties to set the same. The next code example shows a modified class A, which uses a bean property-based IoC.
Class A {  private B b;  public A(){     }   public setB(B b) {   this.b = b;     }    public void doSomething(){   b.someMethod();     }  }
As you may have realised, the fundamental idea behind IoC is to completely decouple objects from explicit dependency. In IoC, one object exposes its dependency to other objects through a defined contract in terms of a constructor or bean property.

There is another way to decouple the objects: dependency lookup. This is implemented as a Service Locator pattern. In dependency lookup, the dependent object explicitly performs a look-up for the required Service objects. By doing so, the Service Locator can return various versions and flavors of the required Service objects. Thus, the dependent object does not need to use any explicit reference to any implementation of the Service object. However, the dependent object still needs to know about the Service Locator component.

Comparing the Two Methods

So far, you've seen two methods of passing the dependency to the object: one through constructors and the other through appropriate setter methods. As usual, both methods have their pros and cons.

Here's the advantages of using the constructor-based IoC:

  • You can hide (or encapsulate) all your fields without having to expose them through setter methods. This is important because if you don't want something to change, youneed to make sure you haven't provided it any way to change.
  • A constructor with a specific number of parameters gives you a clear indication of what it means to create an object.
On the other hand, the disadvantages with constructor-based IoC are:
  • If you've got too many parameters to be passed inside the constructor, it starts looking messy.
  • The order of parameters becomes important.
  • If, at the time of creating the object, you are not sure about the dependencies the object will take up, you may not be able to inject the dependency through a constructor.
  • Constructors can suffer from classic inheritance problems when super class constructors do change or a sub-class is added. (LINK TO MY INHERITANCE VS COMPOSITION ARTICLE). Although, this is more of a problem in the OO domain, it is significant enough here to effect the success of IOC.
The dependency lookup concept works fine, but only if all the application modules are developed under the same hood and you have a thorough knowledge of every API of every component used in the application. If you're developing a component for a third party, you're probably not going to know anything about the kind of service locator component that third party will use. Hence, this model might fail to work.

Taken from -

No comments:

Post a Comment

Amazon Best Sellors

Weblogic - Server Creation - Issues

Datasource creation using python script.  Python Script was failing after creating Datasource. From UI Admin Console, if I try to activat...