Talk about dependency injection
In object-oriented programming, the problem we often deal with is decoupling. The lower the coupling of the program indicates the readability and maintainability of the program. Inversion of Control (Inversion of Control or IoC) is a commonly used design principle of object-oriented programming. Using this principle we can reduce coupling. Among them, dependency injection is the most commonly used implementation of control inversion.
What is dependency
Dependency is a common phenomenon in programs. For example, the instance energy of the GasEnergy class is used in class Car. The usual practice is to explicitly create an instance of the GasEnergy class in the Car class and assign it to energy. As shown in the following code
interface Energy { } class GasEnergy implements Energy { } class Car { Energy energy = new GasEnergy();}There are problems
Class Cars assume unnecessary responsibilities and are responsible for the creation of energy objects, which inevitably has serious coupling. To give a realistic example, it is the responsibility of the car to use which energy a car uses not depends on the car, but on the car manufacturer.
Scalability. Assuming that we want to modify the energy to electric power, then we must modify the Car class, which obviously does not comply with the principle of open closure.
Not conducive to unit testing.
Dependency injection
Dependency injection is such a behavior. In the class Car, the GasEnergy object is not actively created, but the dependency is set by passing it in the GasEnergy object form externally. There are three common methods of dependency injection.
Constructor injection
Pass the required dependency as parameters of the constructor to complete dependency injection.
class Car { Energy mEnergy; public Car(Energy energy) { mEnergy = energy; }}Setter method injection
Add the setter method, the parameter is the dependency that needs to be injected, and the dependency injection can be completed.
class Car { Energy mEnergy; public void setEnergy(Energy energy) { mEnergy = energy; }}Interface injection
Interface injection is self-evident, it is to create a set of interfaces for dependency injection, and the dependency is passed as parameters, and the dependency injection to the specific implementation is completed by calling a unified interface.
interface EnergyConsumerInterface { public void setEnergy(Energy energy);} class Car implements EnergyConsumerInterface { Energy mEnergy; public void setEnergy(Energy energy) { mEnergy = energy; }}Interface injection is similar to setter method injection, the difference is that interface injection uses a unified method to complete the injection, while the method name of the setter method injection is relatively casual.
Framework trade-offs
There are many frameworks for dependency injection, the most famous one is Guice. Of course, Spring also supports dependency injection. Guice uses runtime reading annotations, generates dependencies and injects them through reflection. This form is not very suitable for Android mobile devices. After all, these operations are processed at runtime and have high performance requirements.
Dagger is a suitable dependency injection library for Android development. It also uses the form of class annotations. The difference is that it generates auxiliary classes at compile time and waits until the generated auxiliary classes are used to complete dependency injection at runtime.
Use or not
In fact, whether to use or not to use the framework is a problem. If you use the framework, everyone in the team is required to follow the instructions to write code to solve the dependency injection. These frameworks are not easy to get started, and the learning coefficients are relatively complex and difficult to master, which is also a problem that needs to be considered.
My personal opinion is that we do not recommend or oppose the use of these frameworks, but I feel that sometimes we hope for a framework, so it is better to pay attention to these issues in our daily life. Isn’t artificial avoidance also a basic requirement for ourselves?
Dependency search
Dependency search is the specific implementation of the control inversion principle, unlike the passive acceptance of dependency injection, dependency search is an active request. When needed, the object is obtained by calling the methods provided by the framework. When obtaining, relevant configuration file paths, keys and other information are required to determine the state of the object being obtained.
The above is a detailed introduction to the information on dependency injection. We will continue to add relevant information in the future. Thank you for your support to this site!