Two important guidelines on the principle of dependency inversion
A. High Level modules shoshould not depend upon Low Level modules. Both shoulddepend upon implements actions.
High-level modules should not depend on low-level modules, both of which should depend on abstraction.
B. Define actions shocould not depend upon details. Details shocould depend uponappsactions.
Abstraction should not depend on details, and details should depend on abstraction
Concepts:
Dependency: InProgramIn the design, if one module A uses/calls another Module B, we call it module A dependent on Module B.
Low-level modules: we usually have some low-level classes in an application, which implement some
Basic or elementary operations are called low-layer modules;
High-level module: there are also some high-level classes that encapsulate some complex logic and depend on
Low-level classes are called high-level modules.
Let's take a look at the dependency types, which are coupling. There are three types:
----- Nil coupling relationship. The two classes have no dependency, that is, zero coupling.
----- The concrete coupling relationship. The two classes are dependent on each other,
This is the specific coupling relationship. If a specific class directly references another specific class
This relationship is generated.
----- Abstract coupling relationship, which occurs in a specific class and a smoke
In this way, the maximum flexibility is maintained between classes that must have a relationship.
Why is dependency inversion?
The dependency between object-oriented programming and process-oriented (structured) programming is put upside down. In traditional Structured Programming, high-level modules always rely on low-level modules.
Dependency inversion(Dependence inversionprinciple) Principle: To rely on abstraction, not specific.
In short, the dependency inversion principle requires the client to rely on abstract coupling. Principles:
Abstraction should not depend on details; details should depend on abstraction;
Programming for interfaces is not implemented.
Question proposal
Robert C. Martin defines "bad design" in the original article:
1. It is hard to change because every change affects too your other parts ofthe system. (rigidity)
The system is hard to change, because every change affects many other parts.
2. When you make a change, unexpected parts of the system break. (fragility)
When you make a change to a place, other seemingly unrelated parts of the system will not work.
3. It is hard to reuse in another application because it cannot be disentangledfrom the current application. (immobility)
It is difficult for the system to be reused by another application, because it is difficult for you to separate the reusable parts from the system.
A major cause of "bad design" is that "high-level modules" rely too much on "low-level modules ".
A good design should be that every part of the system is replaceable.
If the "high-level module" is too dependent on the "low-level module ":
On the one hand, once the "low-level module" needs to be replaced or modified, the "high-level module" will be affected;
On the other hand, it is difficult for high-level modules to be reused.
For example, in a copy module, You need to copy the input from the keyboard to print,
Even if the encapsulation of keyboard and print has been done very well, if the keyboard and print are directly used in the copy module,
Copy is hard to be reused by other application environments (such as when output to a disk.
Solution:
To solve the above problem, Robert C. Martin's proposed the Dependency inversion principle (DIP) principle designed by oo.
Dip provides a solution:
An abstract interface layer is introduced between a high-level module and a low-level module.
High level classes (high-level module) -->
Abstract action layer -->
Low level classes (low level module)
An abstract interface is an abstraction of a lower-level module. a lower-level module inherits or implements this abstract interface.
In this way, the high-level module does not directly depend on the lower-level module. Both the high-level module and the lower-level module depend on the abstract interface layer.
Of course, abstraction does not depend on the implementation details of the lower-layer modules. The lower-layer modules depend on (inherit or implement) abstract definitions.
Structure of the dip scheme class given by Robert C. MARTIN:
Policylayer -->
Mechanical interface (abstract) -->
Mechanismlayer -->
Utilityinterface (abstract) -->
Utilitylayer
Classes and classes are combined through abstract layer.
Instance description dip
Negative example:
Disadvantage: If the coupling is too tight, changing light will affect toggleswitch.
Solution 1:
Abstract light and inherit the class from light.
Advantage: toggleswitch depends on the abstract class light and has higher stability. bulblight and tubelight inherit from light and can be expanded based on the "open-closed" principle. As long as the light does not change, the changes between bulblight and tubelight will not affect toggleswitch.
Disadvantage: it is very difficult to use toggleswitch to control a TV. TV cannot be inherited from light.
Solution 2:
Advantage: it is more general and stable.
Summary
Dip requires the client to rely on abstract coupling. abstraction should not depend on details, and details should depend on abstraction (abstractionsshocould not depend upon details. details shoshould depend upon implements actions), another expression of this principle is the one emphasized by the "four-person group": To program interfaces, do not implement programming (program to aninterface, not an implementation), when the program needs to reference an object, it should try to use the abstract type as the static type of the variable, which is the meaning of interface programming. DIP is a way to achieve the "open-closed" principle.
To achieve dip, abstract coupling is the key. Because an abstract coupling always involves the inheritance of a specific class from an abstract class. It is also necessary to ensure that the sub-classes can be changed to any reference to a certain type. Therefore, LSP is the basis of dip. DIP is the core principle of OOD. The research and application of design patterns use it as the guiding principle. Although dip is powerful, it is difficult to implement it. In addition, dip assumes that all specific classes will change, which is not all right. Some specific classes are quite stable. The client that uses this class can depend entirely on this specific class without having to create another abstract class.