Difference between creating new object and dependency injection
What is the开发者_运维问答 difference between creating a new object and dependency injection? Please explain in detail.
Well, they're not exactly comparable. You will always have to create a new object by instantiating a class at some point. Dependency injection also requires creating new objects.
Dependency injection really comes into play when you want to control or verify the behavior of instances used by a class that you use or want to test. (For Test Driven Development, dependency injection is key for all but the smallest example).
Assume a class Holder which requires an object of class Handle. The traditional way to do that would be to let the Holder instance create and own it:
class Holder {
private Handle myHandle = new Handle();
public void handleIt() {
handle.handleIt();
}
}
The Holder instance creates myHandle and no one outside the class can get at it. In some cases, unit-testing being one of them, this is a problem because it is not possible to test the Holder class without creating the Handle instance which in turn might depend on many other classes and instances. This makes testing unwieldy and cumbersome.
By injecting the Handle instance, for example in the constructor, someone from the outside becomes responsible for the creation of the instance.
class Holder {
private Handle myHandle;
public Holder(Handle injectedHandle) {
myHandle = injectedHandle;
}
public void handleIt() {
handle.handleIt();
}
}
As you can see the code is almost the same, and the Handle is still private, but the Holder class now has a much loser coupling to its outside world which makes many things simpler. And when testing the Holder class a mock or stub object can be injected instead of a real instance making it possible to verify or control the interaction between the Holder, its caller and the handle.
The actual injection would take place at some other place, usually some "main" program. There are multiple frameworks that can help you do that without programming, but essentially this is the code in the "main" program:
...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...
In essence, the injection is nothing more than a fancy set
method. And of course, you can implement the injection mechanism using that instead of in the constructor like the simple example above.
Of course, both create objects. The difference is in who is responsible for the creation. Is it the class that needs its dependencies or a container like Spring for example, which wires the component's dependencies? You configure the dependencies in a separate(typically XML) configuration file.
It is really a separation of concerns. The class says I need this, this, and this component to function properly. The class doesn't care how it gets its components. You plug them into the class with a separate configuration file.
To give you an example let's consider having a shopping class that needs a payment module. You don't want to hardcode which payment module will be used. To achieve this you inverse the control. You can change the used payment module with a few keystrokes in the configuration file of the container. The power is that you aren't touching any Java code.
Well, creating a new object is as explicit as it can get - you create a new instance of the desired class.
Dependency injections is a mechanism that provides you with references where you need them. Imagine a class that represents a connection pool to your database - you usually only have one instance of that class. Now you need to distribute that reference to all the classes that use it. Here is where Dependency Injection comes in handy - by using a DI framework such as Spring you can define that the one instance of your pool will be injected into the classes that need it.
Your question itself is not easy to answer since the creation of an object and dependency injection can't be compared that easily...
Dependency injections adds a layer of configurability into your application. In the sense, when you hard code object construction, you need to re-build and re-deploy your app, but when you use dependency injection, you can re configure the XML and change the behavior without re-building and re-deploying. There are a large variety of use cases where this can save a lot of tie and effort.
When using an inversion-of-control container to perform dependency injection, the container creates the objects, and not the developer. This is done so that the container can "inject" these objects into other objects.
The answer to the following question may also give the answer you are looking for: Why is the new operator an anti-pattern? Well, the simple answer is that using the new operator may create a hidden, inaccessible dependency within the containing class. This makes testing the containing class more difficult because it involves testing the hidden dependency at the same time (barring MOCK frameworks of course). However, you can avoid this situation by not using the new operator and injecting the dependent object instead. This also has the following advantages:
- For test purposes you can inject a different object.
- The resulting containing class is more reusable because it can support different implementations of the dependent object.
精彩评论