Dependency inversion principle (dependence inversion Principle) dependency inversion principle (DIP)
Basic Concepts
Original Definition
- High-level modules should not rely on low-layer modules, both should rely on their abstraction
- Abstraction should not depend on details
- Detail should be dependent on abstraction
In Java.
specific meaning
- Dependencies between modules occur through abstraction
- There is no direct dependency between the implementation classes
- Its dependencies are generated through interfaces or abstract classes .
- An interface or abstract class does not depend on a specific implementation
- Implementing a class-dependent interface or abstract class
dependency Inversion (DIP)The benefits
- Dip can reduce the coupling between classes, improve stability , reduce the risk of parallel development, improve code readability and maintainability
- by abstracting (interfaces or abstract classes) the implementations of each class and module are independent of each other and do not affect each other, allowing for loose coupling between modules
- Dip is the basis of opening and closing principle
Example Dip
For example, we have a scene where students write homework with a pen. If we implement directly, then when the needs change, the students to use strokes to draw, we have to modify the job class, then do not meet the open and close principle, and each expansion will destroy the previous class, this is not friendly, then how to design the scene according to the dip?
Abstraction of interfaces and the use of abstract interfaces to establish linkages
interface Tool{ publicvoiddoWork( Job job );}interface people{ publicvoiduse ( Tool tool , Job job );}interface Job{ publicvoidfinish();}
We abstracted out people, work, tasks three abstract interfaces , and then we build relationships with three abstract interfaces using a scenario where people use tools to do their work
To implement specific logic separately
class Student1 implements person {@Override Public voidUse (tool tool, Job Job) {System.out.print ("Student use"); Tool.dowork (Job); }} class Pencil implements Tool{@Override Public voidDoWork (Job Job) {System.out.print ("Pencile to Do"); Job.finish (); }} class homework implements Job{@Override Public voidFinish () {System.out.println ("homework!!"); }}
Three classes can be implemented in parallel, with no coupling at all, enabling modular and parallel development of programs
So let's test it out:
publicclass DIPTest { publicstaticvoidmain ( String [] args ){ new Student1(); new Pencil(); new HomeWork(); student.use(pencil,homeWork); }}
When we need to implement the same relationship of the new class, only need to expand on it, such as teachers can still take this model with handouts, can be developed according to the module, in the team to develop the project when the effect is obvious
Classic examples in the real world
TDD (test Driving developing) test-driven development
is to take advantage of a contractual pattern:
- Interface is provided first
- Then we write the unit test class by using the relation and method of the interface.
- And then write the implementation class, which is very helpful for improving the quality of the code, especially for the development of the project or the overall level of the project members in the case of low
Java design mode (12) dependency inversion principle (DIP)