Dependecy Injection ;
1. Dependency injection is a style of object configuration in which an objects fields and collaborators are set by an external entity. In other words objects are configured by an external entity. Dependency injection is an alternative to having the object configure itself.
The Person class itself instantiates a Name as its Name implementation. Therefore the Person class is said to "satisfy its own dependencies". When a class satisfies its own dependencies it automatically also depends on the classes it satisfies the dependencies with. In this case Person now also depends on Name , and on the three hardcoded string values passed as parameter to the Person constructor. You cannot use a different value for the four strings, nor use a different implementation of the Name interface, without changing the code.
As you can see, when a class satisfies its own dependencies it becomes inflexible with regards to these dependencies. This is bad. This means, that if you need to change the dependencies you will have to change the code.
Let's change the design a little:
Dependency injection is not restricted to constructors. You can also inject dependencies using setter methods, or directly into public fields.
If some components are configured as singletons some containers are able to call methods on the singleton when the container is shut down. That way the singleton can release any resources it may hold, like database or network connections. This is often referred to as "instance life cycle management". This means that the container is capable of managing the component throughout the various stages of the components life cycle. For instance, instantiation, configuration and disposal.
The fact that the container sometimes keep a reference to the components after instantiation is the reason it is called a "container", and not a factory. Dependency injection containers usually only keep a reference to objects it needs to manage life cycles for, or that are reused for future injections, like singletons or flyweights. When configured to create new instances of some components for each call to the container, the container usually just forgets about the created object. Otherwise the garbage collector would have a hard time collecting all these objects when no longer used.
There are several dependency injection containers available. Spring, Pico Container, Guice, and others.
1. Dependency injection is a style of object configuration in which an objects fields and collaborators are set by an external entity. In other words objects are configured by an external entity. Dependency injection is an alternative to having the object configure itself.
The Person class itself instantiates a Name as its Name implementation. Therefore the Person class is said to "satisfy its own dependencies". When a class satisfies its own dependencies it automatically also depends on the classes it satisfies the dependencies with. In this case Person now also depends on Name , and on the three hardcoded string values passed as parameter to the Person constructor. You cannot use a different value for the four strings, nor use a different implementation of the Name interface, without changing the code.
public class Person{ protected Name name= new Name("firstName", "middleName", "lastName"); //data access methods... public Person readPerson(int primaryKey) {...} }
As you can see, when a class satisfies its own dependencies it becomes inflexible with regards to these dependencies. This is bad. This means, that if you need to change the dependencies you will have to change the code.
Let's change the design a little:
public class Person { protected Name name= null; public Person(String firstName, String middleName, String lastName){ this.name= new Name(firstName, middleName, lastName); } //data access methods... public Person readPerson(int primaryKey) {...} }Notice how the Name instantiation is moved into a constructor. The constructor takes three parameters which are the four values needed by the Name. Though the Person class still depends on these three values, it no longer satisfies these dependencies itself. They are provided by whatever class creating a Name instance. The values are said to be "injected" into the Person constructor. Hence the term "dependency injection".
Dependency injection is not restricted to constructors. You can also inject dependencies using setter methods, or directly into public fields.
public class Person{ protected Name name= null; public Person(Name name){ this.name = name; } //data access methods... public Person readPerson(int primaryKey) {...} }If all components in your system have their dependencies injected, somewhere in the system some class or factory must know what to inject into all these components. This what a dependency container does. The reason it is called a container and not a factory is that the container often takes on more responsibility than just instantiating objects and injecting dependencies.
If some components are configured as singletons some containers are able to call methods on the singleton when the container is shut down. That way the singleton can release any resources it may hold, like database or network connections. This is often referred to as "instance life cycle management". This means that the container is capable of managing the component throughout the various stages of the components life cycle. For instance, instantiation, configuration and disposal.
The fact that the container sometimes keep a reference to the components after instantiation is the reason it is called a "container", and not a factory. Dependency injection containers usually only keep a reference to objects it needs to manage life cycles for, or that are reused for future injections, like singletons or flyweights. When configured to create new instances of some components for each call to the container, the container usually just forgets about the created object. Otherwise the garbage collector would have a hard time collecting all these objects when no longer used.
There are several dependency injection containers available. Spring, Pico Container, Guice, and others.
There are several benefits from using dependency injection containers rather than having components satisfy their own dependencies. Some of these benefits are:
- Reduced Dependencies
- Reduced Dependency Carrying
- More Reusable Code
- More Testable Code
- More Readable Code
More specifically, dependency injection is effective in these situations:
- You need to inject configuration data into one or more components.
- You need to inject the same dependency into multiple components.
- You need to inject different implementations of the same dependency.
- You need to inject the same implementation in different configurations.
- You need some of the services provided by the container.
These situations have one thing in common. They often signal that the components wired together represent different or independent concepts or responsibilities, or belong to different abstraction layers in the system. For instance, database configuration (driver, url, user, password) and a DataSource implementation are different concepts. Similarly a DataSource and a DAO class represent different concepts and belong to different abstraction layers.
Dependency injection is not effective if:
- You will never need a different implementation.
- You will never need a different configuration.
If you know you will never change the implementation or configuration of some dependency, there is no benefit in using dependency injection.
Difference Between Factory Design Pattern and DI
The Purpose of the Factory Design Patterns
The purpose of the factory patterns is to separate the use of a certain component, from the choice of implementation + instance management of that component. These three separate concerns are repeated here:
- Component Use
- Component Implementation Choice
- Component Instance management