definition: high-level modules should not be dependent on the lower layers, both should rely on their abstraction; abstractions should not depend on detail; detail should be dependent on abstraction.
The problem is that class A is directly dependent on class B, and if you want to change Class A to dependency Class C, you must modify the code of Class A to achieve it. In this scenario, Class A is typically a high-level module that is responsible for complex business logic, and Class B and Class C are low-layer modules that are responsible for basic atomic operations, and if Class A is modified, it poses unnecessary risks to the program.
Solution: Modify Class A to dependent interface I, Class B and Class C each implement interface I, Class A through interface I indirectly with Class B or Class C, it will greatly reduce the chance to modify Class A.
The dependency inversion principle is based on the fact that abstract things are much more stable relative to the variability of details. Structures built on the basis of abstraction are much more stable than structures built on the basis of detail. In Java, abstract refers to an interface or abstract class, the details are specific implementation classes, the use of interfaces or abstract classes to make good specifications and contracts, not to involve any specific operation, the task of presenting details to their implementation class to complete.
The core idea of the dependency inversion principle is interface-oriented programming, and we still use an example to illustrate the interface-oriented programming better than the aspect-oriented implementation. The scene is this, the mother tells the child story, as long as give her a book, she can follow the book to tell the children story. The code is as follows:
classbook{ PublicString getcontent () {return"A long time ago there was an Arab story ..."; }} classmother{ Public voidNarrate (book book) {System.out.println ("Mom started telling stories."); System.out.println (Book.getcontent ()); }} Public classclient{ Public Static voidMain (string[] args) {Mother Mother=Newmother (); Mother.narrate (NewBook ()); }}
Operation Result:
Mom starts telling stories.
A long time ago there was an Arab story ...
Run well, if one day, demand becomes this: not to the book but to a newspaper, let the mother tell the newspaper story, the newspaper code is as follows:
class newspaper{ public String getcontent () { return "Lin 38+7 leads the Knicks to defeat the Lakers ..." ; }}
The mother could not do it, because she could not read the story in the newspaper, this is ridiculous, just to change the book to newspaper, actually must change mother to read. What if the future needs to be replaced by magazines? Instead of a Web page? It is not a good design to constantly modify the mother. The reason is that the coupling between mother and book is too high, and the coupling between them must be reduced.
We introduce an abstract interface, Ireader. Reading, as long as the word belongs to the reading:
Interface ireader{ public String getcontent ();}
Mother class and interface Ireader have a dependency, and book and newspaper belong to the category of reading, each of them to implement the Ireader interface, which conforms to the dependency inversion principle, the code is modified to:
classNewspaperImplementsIreader { PublicString getcontent () {return"Jeremy Lin 17+9 to help the Knicks defeat the Eagle ..."; }}classBookImplementsireader{ PublicString getcontent () {return"A long time ago there was an Arab story ..."; }} classmother{ Public voidNarrate (Ireader reader) {System.out.println ("Mom started telling stories."); System.out.println (Reader.getcontent ()); }} Public classclient{ Public Static voidMain (string[] args) {Mother Mother=Newmother (); Mother.narrate (NewBook ()); Mother.narrate (Newnewspaper ()); }}
Operation Result:
Mom starts telling stories.
A long time ago there was an Arab story ...
Mom starts telling stories.
Jeremy Lin 17+9 to help the Knicks defeat the Eagle ...
After this modification, no matter how to extend the client class later, there is no need to modify the mother class. This is just a simple example, in fact, the mother class representing the high-level module will be responsible for completing the main business logic, once it needs to be modified, the risk of introducing errors is enormous. Therefore, following the dependency inversion principle can reduce the coupling between classes, improve the stability of the system and reduce the risk of modifying the program.
Using the principle of dependency inversion has brought great convenience to the concurrent development of many people, such as the above example, the original Mother class and the book class directly coupled, the mother class must wait for the book class after the completion of the code can be encoded, because the mother class depends on the book class. The modified program can be started at the same time, do not affect each other, because mother and book Class A little relationship. The more people involved in collaborative development and the larger the project, the greater the significance of relying on the principle of dependency. Today's popular TDD development model is the most successful application of the dependency inversion principle.
There are three ways to pass a dependency, the method used in the above example is interface passing, and there are two other ways of passing it: construction method passing and setter method passing, which I believe have been used in spring framework, There must be no strangers to the way of relying.
In actual programming, we generally need to do the following 3 points:
- The low-level module should have an abstract class or interface as much as possible, or both.
- The declaration type of a variable is as abstract a class or interface as possible.
- Follow the Richter substitution principle when using inheritance.
The core of the dependency inversion principle is that we can interface-oriented programming , understand the interface-oriented programming, and understand the dependency inversion.
Design pattern principle Dependency inversion