Dependency injection
From Wikipedia, the free encyclopedia
It has been suggested that Dependency inversion principle be merged into this article or section. (Discuss) |
This article or section includes a list of references or external links, but its sources remain unclear because it lacks in-text citations. You can improve this article by introducing more precise citations. |
Dependency injection (DI) in Computer programming refers to the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency.
Conventionally, if an object needs to gain access to a particular service, the object takes responsibility to get hold of that service: either it holds a direct reference to the location of that service, or it goes to a known 'service locator' and requests that it be passed back a reference to an implementation of a specified type of service. By contrast, using dependency injection, the object simply provides a property that can hold a reference to that type of service; and when the object is created a reference to an implementation of that type of service will automatically be injected into that property - by an external mechanism.
When the dependency injection technique is used to decouple high-level modules from low-level services, the resulting design guideline is called the Dependency inversion principle.
The dependency injection approach offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a mock implementation of a service into the object being tested. On the other hand, excessive use of dependency injection can make applications more complex and harder to maintain: in order to understand the application's behaviour the developer needs to look at the configuration as well as the code, and the configuration is "invisible" to IDE-supported reference analysis and refactoring unless the IDE specifically supports the dependency injection framework.
Contents |
[edit] A Code Illustration using Java
Suppose that IFoo
is a common class, specifying a certain interface:
public interface IFoo { void bar(); // Perform bar void baz(); // perform baz }
There exist also a number of implementation classes, each of them implementing IFoo in some way:
public class DatabaseFoo implements IFoo { void bar() { db.select_bar().execute(); // Use the database to do bar } void baz() { db.select_baz().run(); // Use the database to do baz } }
public class PixieDustFoo implements IFoo { void bar() { cast_spell("bar"); // Magic! } void baz() { cast_spell("baz"); // Magic! } }
public class EnterpriseFoo implements IFoo { void bar() { EnterpriseFactoryObserverFactoryCreator efofc("bar"); efofc.creatify(); efofc.preparify(); efofc.configurise(); efofc.make_award_winning(); efofc.opportunities.leverage(); } void baz() { EnterpriseFactoryObserverFactoryCreator efofc("baz"); efofc.creatify(); efofc.preparify(); efofc.configurise(); efofc.make_award_winning(); efofc.opportunities.leverage(); } }
IFoo
only specifies the operations available in its interface, but doesn't itself provide any implementation, instead leaving that to other implementer classes. This way a user wishing to use the IFoo functionality can use any implementation, not knowing anything more about them than that they conform to the Foo interface.
An object needing the services defined by IFoo
needs to get an instance of a class that implements IFoo
:
public class ImportantClass { IFoo foo; public ImportantClass() { this.foo = new EnterpriseFoo(); } void do_really_important_stuff() { this.foo.bar(); } }
However, this defeats the entire point of using an interface instead of a concrete implementation. To fix that, it's enough to let the outside caller provide the desired implementation:
public ImportantClass(IFoo foo) { this.foo = foo; }
When using dependency injection there is usually a configuration mechanism or architecture for deciding which implementation gets injected into an object.
[edit] Existing frameworks
Dependency injection frameworks exist for a number of platforms and languages including:
ActionScript
- Prana Framework
- di-as3
- Syringe
- lowRa (AS3)
- Pixlib (AS2)
- VEGAS and AndromedA this IOC extension.(AS3/AS2/SSAS) (see Introduction IOC based ECMAScript notation)
C++
ColdFusion
Java
- Seasar
- Spring Framework
- J2EE 5 / EJB 3
- Naked Objects
- miocc - Microscopic Inversion of Control Container
.NET
- Autofac
- Castle MicroKernel/Windsor
- ObjectBuilder
- PicoContainer.NET
- Puzzle.NFactory
- Spring.NET
- StructureMap
- Ninject
- Unity
PHP4
PHP5
Perl
Python
Ruby
[edit] See also
- Closure (computer science) is a method for initializing the dependencies of a callback function in functional programming.
- Strategy pattern
- Architecture description language
[edit] External links
- Inversion of Control Containers and the Dependency Injection pattern - Martin Fowler.
- Dependency Injection & Testable Objects: Designing loosely coupled and testable objects - Jeremy Weiskotten; Dr. Dobb's Journal, May 2006.
- Design Patterns: Dependency Injection -- MSDN Magazine, September 2005
- Writing More Testable Code with Dependency Injection -- Developer.com, October 2006
- Domain Specific Modeling (DSM) in IoC frameworks
- Prasanna, Dhanji R. (2008). Dependency Injection. Manning Publications. ISBN 193398855X.
- What is Dependency Injection? - An alternative explanation - Jakob Jenkov
- The Rich Engineering Heritage Behind Dependency Injection - Andrew McVeigh - A detailed history of dependency injection.