Dependency Injection (DI)
Dependency Injection is a software design concept that allows a service to be used/injected in a way that is completely independent of any client consumption. This prevents the client from modifying when the underlying service changes.
Dependency injection separates the creation of a client’s dependencies from the client’s behavior, which allows program designs to be loosely coupled. I know that might sound like gibberish, but I’m about to explain what this all means in plain and simple English.
Dependency Injection in Plain and Simple English
Dependency Injection can exist between two objects, for instance, a flashlight and a battery. The flashlight needs the battery to function. However, any changes made to the battery, such as switching it with another brand/set of batteries, does not mean the dependent object (flashlight) also needs to be changed.
A flashlight needs power from a battery to produce light. A flashlight that only works with a particular brand of battery is badly designed.
Conclusion
Dependency injection is the art of creating service/client relationships that work well together by injecting services that are easily swapped with minimal time and effort.
Although the components are mutually dependent, replacing one won’t harm or render the other useless.
Understanding Dependency Injection And Containers
Published Jul 06, 2017
Dependency injection and dependency injection containers are different things:
⦁ dependency injection is a method for writing better code
⦁ a container is a tool to help injecting dependencies
Inversion of Control (IoC)
Inversion of Control is what you get when your program callbacks, e.g. like a gui program. For example, in an old school menu, you might have: print “enter your name” read name print “enter your address” read address etc… store in database. thereby controlling the flow of user interaction
Inversion of Control (IoC – “reverse control)“ is a way of creating a program code when its required dependencies are set for it from the outside, by its environment which uses it instead of the program obtaining them itself or creating them itself
The Inversion of Control (IoC) and Dependency Injection (DI) patterns are all about removing dependencies from your code.
For example, say your application has a text editor component and you want to provide spell checking. Your standard code would look something like this:
public class TextEditor { private SpellChecker checker; public TextEditor() { this.checker = new SpellChecker(); }}
What we’ve done here creates a dependency between the TextEditor and the SpellChecker. In an IoC scenario we would instead do something like this:
public class TextEditor { private IocSpellChecker checker; public TextEditor(IocSpellChecker checker) { this.checker = checker; }}
In the first code example we are instantiating SpellChecker (this.checker = new SpellChecker();), which means the TextEditor class directly depends on the SpellChecker class.
In the second code example we are creating an abstraction by having the SpellChecker dependency class in TextEditor’s constructor signature (not initializing dependency in class). This allows us to call the dependency then pass it to the TextEditor class like so:
SpellChecker sc = new SpellChecker(); // dependency
TextEditor textEditor = new TextEditor(sc);
Now the client creating the TextEditor class has control over which SpellChecker implementation to use because we’re injecting the dependency into the TextEditor signature.
What is differences between Dependency Injection (DI) and Inversion of Control (IoC)?
IoC is a design paradigm with the goal of giving more control to the targeted components of your application, the ones getting the work done. While Dependency injection is a pattern used to create instances of objects that other objects rely on without knowing at compile time which class will be used to provide that functionality. IoC relies on dependency injection because a mechanism is needed in order to activate the components providing the specific functionality.
The two concepts work together in this way to allow for much more flexible, reusable, and encapsulated code to be written. As such, they are important concepts in designing object-oriented solutions.