Inversion of control , Dependency Inversion Principle(DIP) And Dependency Injection

Abhinav Jha
5 min readMar 15, 2021

In general terms Ioc and Dip are principles which are used or implemented across object oriented programming architectural paradigm to achieve loose coupling of objects.

What is loose coupling? In Object oriented programming paradigm , objects are created which interact with each other to perform tasks. so, it is the interaction of the object where objects have to be coupled to share data and perform the tasks. In a traditional programming, these objects are very tightly coupled. refer below example

public class A
{
B b;

public A()
{
b = new B();
}

public void Task1() {
// do something here..
b.SomeMethod();
// do something here..
}

}

public class B {

public void SomeMethod() {
//doing something..
}
}

In the above example, the class A is dependent on B. object of B is created with ‘new’ keyword which implies A is highly dependent on B. any subject to cahnge in B will definitely lead to change in A. Class A creates and manages the life time of an object of class B. Essentially, it controls the creation and life time of objects of the dependency class.

The IoC principle suggests to invert the control. This means to outsource the control to another class. In other words, invert the dependency creation control from class A to another class, as shown below.

public class A
{
B b;

public A()
{
b = Factory.GetObjectOfB ();
}

public void Task1() {
// do something here..
b.SomeMethod();
// do something here..
}
}

public class Factory
{
public static B GetObjectOfB()
{
return new B();
}
}

class A uses Factory class to get an object of class B. Thus, we have inverted the dependent object creation from class A to Factory. Class A no longer creates an object of class B, instead it uses the factory class to get the object of class B

But still classes are tightly couple because Class A still needs the object of core class B which any subject to change will lead to change in class A.

To remove this dependency on core class, we can use DIP principle along with IOC .

Dependency Inversion Principle(DIP)?

it suggests to rules to follow :-

  1. High-level modules should not depend on low-level modules. Both should depend on the abstraction.
  2. Abstractions should not depend on details. Details should depend on abstractions.

As per the DIP rules, a high-level module should not depend on low-level modules. Both should depend on abstraction. So, first, decide which is the high-level module (class) and the low-level module. A high-level module is a module which depends on other modules. In our example, A depends on the B class, so class A is a high-level module and class B is a low-level module. So, as per the first rule of DIP, class A should not depend on the concrete Class B , instead both classes should depend on abstraction.

Abstraction in programming means to create an interface or an abstract class which is non-concrete. This means we cannot create an object of an interface or an abstract class. As per DIP, A (high-level module) should not depend on the concrete B class (low-level module). Both classes should depend on abstractions, meaning both classes should depend on an interface or an abstract class. refer example below

public interface IB
{
string SomeMethod();
}
public class B implements IB
{
public B()
{
}

public string SomeMethod() {
return "Dummy Customer Name";
}
}
public class Factory
{
public static IB SomeMethod()
{
return new B();
}
}
public class A
{
IB b;

public A()
{
b = Factory.SomeMethod();
}

public string someMethod()
{
return b.SomeMethod();
}
}

Thus, we have implemented DIP in our example where a high-level module (class A) and low-level module (Class B) are dependent on an abstraction (Interface IB). Also, the abstraction (Interface IB) does not depend on details (class B), but the details depend on the abstraction.

The advantages of implementing DIP in the above example is that the A and B classes are loosely coupled classes because A does not depend on the concrete B class, instead it includes a reference of the ‘IB’ interface. So now, we can easily use another class which implements ‘IB’ interface with a different implementation.

Still, we have not achieved fully loosely coupled classes because the A class includes a factory class to get the reference of ‘IB’ interface. This is where the Dependency Injection pattern helps us. now, we will learn how to use the Dependency Injection (DI) using the above example.

Dependency Injection?

Dependency Injection (DI) is a design pattern used to implement IoC. It allows the creation of dependent objects outside of a class and provides those objects to a class through different ways. Using DI, we move the creation and binding of the dependent objects outside of the class that depends on them.

The Dependency Injection pattern involves 3 types of classes.

  1. Client Class(A): The client class (dependent class) is a class which depends on the service class
  2. Service Class(B): The service class (dependency) is a class that provides service to the client class.
  3. Injector Class(C): The injector class injects the service class object into the client class.

Injector class injects the dependency in Broadly three ways.

  1. Constructor injection
  2. Setter Injection
  3. Field Injection

we will discuss about constructor injection.

public class A
{
IB b;

public A(IB b)
{
this.b = b;
}

public A()
{
b = new B();
}

public string ProcesData()
{
return b.someMethod();
}
}

public interface IB
{
string someMethod();
}

public class B implements IB
{
public B()
{
}

public string someMethod()
{
return "Dummy Customer Name";
}
}
public class C
{
A a;

public C()
{
this.a = new A(new B());
}

public string someMethod() {
return a.someMethod();
}
}

As you can see in the above example, the ‘C’ class creates and injects the ‘B’ object into the ‘A’ class. Thus, the ‘A’ class doesn't need to create an object of ‘B’ using the new keyword or using factory class. The calling class (C) creates and sets the appropriate B class to the A class. In this way, the A and B classes become "more" loosely coupled classes.

--

--