We use Dependency Injection (DI) to implement loose coupling. The choice of any particulary DI Container is not that important.
Every time you create an instance of a class by using the new
keyword, you tightly couple your code to that class, and you will not be able to substitute that particularl implementation with a different one (at least not without recompiling the code).
This would look something like this in C# (but would be equivalent in Java):
public class MyClass
{
public string GetMessage(int key)
{
return new MessageService().GetMessage(key)
}
}
This means that if you would later like to use a different MessageService, you can't.
On the other hand, if you inject an interface into the class and adhere to the Liskov Substition Principle, you will be able to vary the consumer and the service independently.
public class MyClass
{
private readonly IMessageService messageService;
public MyClass(IMessageService messageService)
{
if(messageService == null)
{
throw new ArgumentNullException("messageService");
}
this.messageService = messageService;
}
public string GetMessage(int key)
{
return this.messageService.GetMessage(key)
}
}
Although this looks more complicated, we have now managed to follow the Single Responsibility Principle by ensuring that each collaborator does only one thing, and that we can vary both independently of each other.
Furthermore, we can now change MyClass' behavior without changing the class itself, thus adhering to the Open/Closed Principle.