Design pattern series [7]: Dependency Inversion Principle -- object-oriented design principle

In the first two sections, we introduced the principles of object-oriented design in detail Opening and closing principle and Richter substitution principle , in this section, we will introduce the dependency inversion principle.

1, Definition of dependency inversion principle

Dependency Inversion Principle (DIP) is an article published by Robert.C.Martin, President of Object Mentor company, on C++ Report in 1996.

The original definition of dependency inversion principle is: high-level modules should not rely on low-level modules, and both should rely on their abstraction; Abstractions should not depend on details. Details should depend on abstractions (high level modules should not depend upon upon low level modules. Both should depend upon upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions). Its core idea is: interface oriented programming, not implementation oriented programming.

Dependency inversion principle is one of the important ways to realize the opening and closing principle, which reduces the coupling between customers and implementation modules.

In software design, the details are changeable, while the abstraction layer is relatively stable, so the architecture based on abstraction is much more stable. The abstraction here refers to the interface or abstract class, while the detail refers to the specific implementation class.

The purpose of using interfaces or abstract classes is to formulate specifications and contracts without involving any specific operations, and hand over the task of showing details to their implementation classes.

2, The role of the principle of dependence and inversion

The main functions of the dependency inversion principle are as follows:

  • The dependency inversion principle can reduce the coupling between classes;
  • The dependence inversion principle can improve the stability of the system;
  • Relying on the inversion principle can reduce the risk caused by parallel development;
  • The dependency inversion principle can improve the readability and maintainability of the code;

3, Implementation method of dependency inversion principle

The purpose of dependency inversion principle is to reduce the coupling between classes through interface oriented programming. Therefore, we should follow the following four points in actual programming to meet this rule in the project.

  1. Each class shall provide interfaces or abstract classes as much as possible, or both;
  2. The declaration type of variable should be interface or abstract class as far as possible;
  3. No class should derive from a concrete class;
  4. Try to follow the principle of inner substitution when using inheritance.

Take "customer shopping program" as an example to illustrate the application of the dependency inversion principle:

[example 1] Application of dependency inversion principle in "customer shopping program"

Analysis: this procedure reflects the relationship between "customers" and "stores". There is a sell() method in the store class. The customer class purchases through this method. The following code defines that the customer class purchases through Shaoguan online store ShaoguanShop:

class Customer {
    public void shopping(ShaoguanShop shop) {
        //shopping
        System.out.println(shop.sell());
    }
}

However, this design has disadvantages. If the customer wants to shop from another store (such as WuyuanShop), the customer's code should be modified as follows:

class Customer {
    public void shopping(WuyuanShop shop) {
        //shopping
        System.out.println(shop.sell());
    }
}

Every time customers change a store, they have to modify the code, which obviously violates the opening and closing principle. The reason for the above shortcomings is that the customer class is bound to the specific store class in the design, which violates the dependency inversion principle. The solution is to define the common interface Shop of "Wuyuan online store" and "Shaoguan online store". The customer class is programmed for this interface, and the code is modified as follows:

class Customer {
    public void shopping(Shop shop) {
        //shopping
        System.out.println(shop.sell());
    }
}

In this way, no matter what store the Customer visits or adds a new store, there is no need to modify the original code. The class diagram is shown in Figure 1:

The program code is as follows:

package principle;
public class DIPtest {
    public static void main(String[] args) {
        Customer wang = new Customer();
        System.out.println("Customers buy the following goods:");
        wang.shopping(new ShaoguanShop());
        wang.shopping(new WuyuanShop());
    }
}
//Shop
interface Shop {
    public String sell(); //sell
}
//Shaoguan online store
class ShaoguanShop implements Shop {
    public String sell() {
        return "Shaoguan local specialties: mushrooms, fungus";
    }
}
//Wuyuan online store
class WuyuanShop implements Shop {
    public String sell() {
        return "Wuyuan local specialties: green tea, lees fish";
    }
}
//customer
class Customer {
    public void shopping(Shop shop) {
        //shopping
        System.out.println(shop.sell());
    }
}

The running results of the program are as follows:

Customers buy the following goods:
Shaoguan local specialties: mushrooms, fungus
 Wuyuan local specialties: green tea, lees fish

Keywords: Design Pattern

Added by musson on Sat, 29 Jan 2022 13:41:37 +0200