Design Mode - Software Design Principles 3- Dependency Inversion Principle

When the Dependency Inversion Principle (Dependence Inversion Principle, DIP) refers to the design code structure, layer module should not rely on the underlying module, both of which should depend abstraction. Abstract should not rely on details; details should depend on the abstract . By relying inversion can reduce the coupling between the class and class, and improve system stability, improve the readability and maintainability of the code, and the program can be modified to reduce the risks caused . Next, look at a case, or in the curriculum, for example, to create a first class Tom:

Package. 1 com.lch.test.inversedependency; 
 2 
 . 3 public class Tom { 
 . 4 public void studyJavaCourse () { 
 . 5 System.out.println ( "Tom is learning Java program" );  . 6  }  . 7  . 8 public void studyPythonCounse () {. 9 System.out.println ( "tom are learning python course" ); 10 } 11}

To call it:

1 package com.lch.test.inversedependency;
2 
3 public class StudyCourseTest {
4     public static void main(String[] args) {
5         Tom tom = new Tom();
6         tom.studyJavaCourse();
7  tom.studyPythonCounse(); 8  } 9 }

Tom loves to learn, and is currently learning Python and Java curriculum courses. We all know that learning is also addictive. With the surge of interest in learning, learning courses now Tom would like AI Artificial Intelligence. Then if industry business expansion, our code from the bottom to the top (call level) once to modify the code. Tom studyAICourse increase in class () method, but also in additional high-level calls. Thus, after the system release, in fact, it is very unstable, modifying the code will also bring unexpected risks. Next, we optimized code, create a curriculum abstract ICourse interfaces:

 

1 package com.lch.test.inversedependency;
2 
3 public interface ICourse {
4     void study();
5 }

Then write JavaCourse categories:

Package. 1 com.lch.test.inversedependency; 
2 
. 3 public class JavaCourse the implements ICourse { 
. 4     @Override 
. 5 public void Study () {  . 6 System.out.println ( "Tom is learning Java program" );  7 } 8}

And then realize PythonCourse class

Package. 1 com.lch.test.inversedependency; 
2 
. 3 public class PythonCourse the implements   ICourse { 
. 4     @Override 
. 5 public void Study () {  . 6 System.out.println ( "Tom is studying python course" );  7 } 8}

Tom modified class, the incoming interface implemented Icourse study methods:

Package. 1 com.lch.test.inversedependency; 
 2 
 . 3 public class Tom { 
 . 4 / * public void studyJavaCourse () { 
 . 5 System.out.println ( "Tom is learning Java program"); 
 . 6} 
 . 7 
 . 8 public void studyPythonCounse () { 
 . 9 System.out.println ( "Tom is studying python course"); 
10} * / 
. 11 public void study ( ICourse course ) { 
12 is  course.study ();  13 is  }  14}

And then continues to call:

 1 package com.lch.test.inversedependency;
 2 
 3 public class StudyCourseTest {
 4     public static void main(String[] args) {
 5         Tom tom = new Tom();
 6        /* tom.studyJavaCourse();
 7         tom.studyPythonCounse();*/
 8        tom.study(new JavaCourse());
 9        tom.study(new PythonCourse()); 10  } 11 }

This time we'll view the code, no matter how soaring Tom interest for the new course, I only need to create a new class, tell Tom mass participation by the way, without the need to modify the underlying code. In fact, this is a very familiar way, called dependency injection. There constructor injection way way way and setter. We look constructor injection method:

Package. 1 com.lch.test.inversedependency; 
 2 
 . 3 public class Tom { 
 . 4 / * public void studyJavaCourse () { 
 . 5 System.out.println ( "Tom is learning Java program"); 
 . 6} 
 . 7 
 . 8 public void studyPythonCounse () { 
 . 9 System.out.println ( "Tom is studying python course"); 
10} * / 
. 11 
12 is / public void * study (ICourse course) { 
13 is course.study (); 
14} * / 
15 
16   Private ICourse course;  . 17 
18 is    public Tom (ICourse Course) {  . 19 this.course = Course; 20 is } 21 is 22 is   public void study(){ 23 course.study(); 24 } 25 }

transfer:

According to constructor injection mode, when you call, every time create an instance. Well, if Tom is a global singleton, then we can only choose a way to inject Setter, Tom continued to modify the code like:

Package. 1 com.lch.test.inversedependency; 
 2 
 . 3 public class Tom { 
 . 4 / * public void studyJavaCourse () { 
 . 5 System.out.println ( "Tom is learning Java program"); 
 . 6} 
 . 7 
 . 8 public void studyPythonCounse () { 
 . 9 System.out.println ( "Tom is studying python course"); 
10} * / 
. 11 
12 / * 
13 // configured injection 
14 public void study (ICourse course) { 
15 course.study (); 
16} * / 
. 17 
18 is Private ICourse Course; 
. 19 
20 is / * public Tom (ICourse Course) { 
21 is this.course = Course; 
22 is} * / 
23 is  //setter注入
24     public void setCourse(ICourse course) {
25         this.course = course;
26     }
27 
28     public void study(){
29         course.study();
30  } 31 }

Calling code:

The final UML class diagram:

To remember: abstract basis is much more stable than with the details of the basis to build up infrastructure, so take after the demand for programming to an interface, then the details of the first top-level design code structure.

 

Guess you like

Origin www.cnblogs.com/enjoyjava/p/11334837.html