Follow by Email

Wednesday, March 18, 2015

Inversion Of Control, Dependency injection and Java


What are Inversion of Control and Dependency Injection

    Inversion of control is a technique that allows to ease coupling in your programs. Dependency injection is a type of IoC that allows to get needed dependencies. 

Example

    Lets for example assume that you have the ICar and IEngine interfaces that represent abstract car and abstract engine. A car can start the engine and IEngine interface has ignite method which makes ignition. Than lets imagine that you are asked to implement that interfaces for really fast car with really powerful engine.
public interface IEngine {
    void ignite();
}

public interface ICar {
    void engineStart();
}

public class FastCar implements ICar {

    private IEngine mEngine;

    public FastCar(final IEngine engine) {
        mEngine = engine;
    }
    @Override
    public void engineStart() {
        mEngine.ignite();
    }
}

public class PowerfulEngine implements IEngine {
    @Override
    public void ignite() {
        System.out.println("Ignition");
    }
}
And to construct your car you shall do:
FastCar car = new FastCar(new PowerfulEngine());
Pretty easy. Yes. But what if you have a complex program where you have to pass your object through the hierarchy of classes. Not so pleasant. Or maybe you want to use the same engine in different cars. You will have to store and pass the same engine to every car.
That is what Inversion of Control is used.   
public class FastCar implements ICar {

    public FastCar() {
    }
    @Override
    public void engineStart() {
        try {
            IoCContainer.resolve(IEngine.class).ignite();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Much easier.

End

   Now a couple words about how to use IoCContainer that is attached to this article.
First of all it's basic realization and you can improve it a lot. For example add registration of created object. To use current realization mark constructor of your class with @ResolveAnnotation annotation to mark constructorthat must be used for object creation like this: 
public class TestClass {

    @ResolveAnnotation
    public TestClass() {}
}
Then register it and resolve when you need it:

IoCContainer.register(TestClass.class);
IoCContainer.resolve(TestClass.class);
To bind class on interface use:

IoCContatiner.register(IInterface.class, IImplementation.class);
IoCContatiner.resolve(IInterface.class);
Link to github with code for IoCContatiner