Java internal power practice series: dependency inversion, control inversion, and dependency injection

table of Contents

1. Explanation of terms

1.1 Dependency inversion principle

1.2 Upper / Bottom Module

1.3 Dependency

2 Dependency inversion

2.1 Before relying on inversion

2.1 After dependency inversion

Three control inversion (IoC)

Four dependency injection (Dependency injection)


1. Explanation of terms

1.1 Dependency inversion principle

The principle of dependency inversion comes from six major design principles of software design, which are defined as follows:

  • Upper-level modules should not depend on lower-level modules, they should all rely on abstraction.

  • Abstraction should not depend on details, details should depend on abstractions.

Note : The high-level module is the calling end, and the low-level module is the concrete implementation class. Abstraction refers to interfaces or abstract classes. The details are the implementation class.

In layman's terms:  the essence of the dependency inversion principle is to make the realization of various types or modules independent of each other through abstraction (interface or abstract class) without affecting each other, and realize loose coupling between modules.

Problem description:  Class A directly depends on class B. If you want to change class A to depend on class C, you must achieve it by modifying the code of class A. In this scenario, class A is generally a high-level module responsible for complex business logic; class B and class C are low-level modules responsible for basic atomic operations; if class A is modified, it will bring unnecessary risks to the program.

Solution:  Modify class A to depend on the interface interface. Class B and class C each implement the interface interface. Class A indirectly communicates with class B or class C through the interface interface, which will greatly reduce the chance of modifying class A.

1.2 Upper / Bottom Module

In an analogy company, the management is the upper level, and the CEO is the upper level of the entire business group, then the CEO function is the bottom level. Each department manager above is the upper layer, then the organizations below can be called the bottom layer. From this, we can see that in a particular system, the upper module and the lower module can be divided according to the level of decision-making ability. Then, mapping to the actual development of our software, generally we will also divide the software into modules, such as business layer, logic layer and data layer.

The business layer is what the software really wants to do , that is, what to do . The logic layer is the implementation details provided by the software at the current stage for the needs of the business layer, that is, how to do it . The data layer refers to the data model required by the business layer and the logic layer. As summarized above, the modules are divided according to the level of decision-making ability. The business layer is naturally in the upper layer module, and the logic layer and the data layer are naturally classified as the bottom layer.

1.3 Dependency

To put it simply, Class A holds Class B references, and Class A depends on Class B. In the following example, Person holds a reference to Car, and Person depends on Car.

public class Person {

    private Car mCar;

    public Person() {
        mCar = new Car();
    }
}

2 Dependency inversion

2.1 Before relying on inversion

In previous developments, we would write code like this:

public class Person {

    private Bike mBike;
    private Car mCar;
    private Plane mPlane;

    public Person(){
        mBike = new Bike();
    }

    public void goToBeijing(){
        System.out.println("以某种交通方式去北京");
        mBike.drive();
    }

    public static void main(String ... args){
        Person person = new Person();
        person.goToBeijing();
    }
}

We created a Person class. Person can choose any transportation method to go to Beijing. Of course, no matter which transportation method, driving a car or flying, each transportation method includes a goToBeijing () method for Person to call.

This is the basic code. In the analogy of the actual code, the vehicle will definitely be changed frequently. At this time, the dependent objects in the Person will be frequently changed, that is, the new vehicle (car or plane or bike) in the Person class needs to be changed. , Code changes, many, annoying, high coupling.

Is there any way to solve the above problem? Rely on the upside down!

2.1 After dependency inversion

Before using dependency inversion, we need to understand the definition of dependency inversion:

  • Upper-level modules should not depend on lower-level modules, they should all rely on abstraction.
  • Abstraction should not depend on details, details should depend on abstractions.

The first is the separation of the upper module and the bottom module. Person relies on traffic to issue travel. Person belongs to the upper module, and Bike, Car, and Train belong to the bottom module. In the previous code, Person relies on transportation to travel.

Let's analyze: Person only wants to go to Beijing, and going to Beijing is abstract. How to go to Beijing, whether to fly or drive a car, this is the detail. The upper-level module is Person. He should rely on abstraction instead of detail. As long as the details are implemented, it is better to go to Beijing to take the specific transportation method (that is, the implementation of the method).

public class Person {

    private Bike mBike;
    private Car mCar;
    private Plane mplane;
    private Driveable mDriveable;

    public Person(){
       mDriveable = new Plane();
    }

    public void goToBeijing(){
        System.out.println("以某种交通方式去北京");
        mDriveable.drive();
    }

    public static void main(String ... args){
        Person person = new Person();
        person.goToBeijing();
    }
}

No matter which travel method Person chooses, to go to Beijing, just call the goToBeijing method. This method will automatically call the drive method of the travel vehicle, because bike or car or airplane, these three travel methods all implement the Driveable interface. This interface is an abstraction. It does not care about the specific implementation of your trip to Beijing, but no matter which transportation mode you choose, you must drive to Beijing.

It can be seen that dependency inversion is essentially a manifestation of interface-oriented programming.


Three control inversion (IoC)

In the above example, we still need to modify the code inside the Person class, and it has not achieved its purpose. Because Person still controls the instantiation of his own mDriveable concrete implementation class. We need to move the instantiation of mDriveable outside of Person, that is to say, Person handed over the control reversal of the instantiation of the internal mDriveable that he controlled, which is the inversion of control, that is, IoC (Inversion of Control ).

public class Person {

    private Driveable mDriveable;

    public Person(Driveable driveable){
        this.mDriveable = driveable;
    }

    public void goToBeijing(){
        System.out.println("以某种交通方式去北京");
        mDriveable.drive();
    }

    public static void main(String ... args){
        Person2 person = new Person2(new Car());
        person.goToBeijing();
    }

}

In this way, no matter what kind of transportation Person chooses to go to Beijing, there is no need to change the interior of the Person class. Person transfers the power of creating internal dependencies to the main () method in the class. It only cares about the functions provided by the dependency, and does not care about the creation of the dependency. It no longer personally creates Driveable objects. The Person class refers to the concept of the IoC container in IoC .

This idea is actually IoC. IoC is a new design pattern that further decouples the upper-layer module and the lower-layer module. Control reversal means reversing the dependency control of the upper layer module on the lower layer module.


Four dependency injection (Dependency injection)

The above is the control reversal, so how to realize the control reversal?

Answer:  Dependency Injection, DI, Dependency Injection. Also often referred to as DI, it is a means of implementing IoC.

In the above example, we handed over the control of Person to dependency instantiation, so what about dependencies? Person cannot be instantiated and dependent, so it needs to be assigned to it externally (IoC container). This assignment action has a special term called injection.

It should be noted that in the concept of IoC, this place for injecting dependencies is called an IoC container, but in the concept of dependency injection, it is generally called an injector.

To put it plainly: I do n’t want to instantiate dependencies myself, you (injector) create them, and then inject them to me when appropriate

There are 3 ways to implement dependency injection:

  1. Constructor injection

  2. Setter injection

  3. Interface injection

/**
 * 接口方式注入
 * 接口的存在,表明了一种依赖配置的能力。
 */
public interface DepedencySetter {
    void set(Driveable driveable);
}
public class Person  implements DepedencySetter {

    //接口方式注入
    @Override
    public void set(Driveable driveable) {
        this.mDriveable = mDriveable;
    }

    private Driveable mDriveable;

    //构造函数注入
    public Person(Driveable driveable){
        this.mDriveable = driveable;
    }

    //setter 方式注入
    public void setDriveable(Driveable mDriveable) {
        this.mDriveable = mDriveable;
    }

    public void goToBeijing(){
        System.out.println("以某种交通方式去北京");
        mDriveable.drive();
    }

    public static void main(String ... args){
        Person2 person = new Person2(new Car());
        person.goToBeijing();
    }
}

 

 

 

 

Reference article:

Easy to learn, analysis of dependency inversion (DIP), control inversion (IOC) and dependency injection (DI): https://blog.csdn.net/briblue/article/details/75093382

 

 

 

Published 174 original articles · Like 433 · Visit 320,000+

Guess you like

Origin blog.csdn.net/LucasXu01/article/details/105462568