Details the dependency inversion principle in Java design pattern programming

  • 2020-04-01 04:39:08
  • OfStack

Definition:
High-level modules should not rely on low-level modules, both should rely on their abstraction; Abstractions should not depend on details; Details should rely on abstractions.
Class A is directly dependent on class b. if you want to change class A to depend on class C, you have to modify the code of class A. In this scenario, class A is typically A high-level module responsible for complex business logic; Classes B and C are low-level modules responsible for basic atomic operations. If you modify class A, you take unnecessary risks to the program.
Solution: modify class A to rely on interface I, class B and class C to implement interface I respectively, and indirectly connect class A to class B or class C through interface I will greatly reduce the chance of modifying class A.
                The dependency inversion principle is based on the fact that abstract things are much more stable than the variability of detail. Architecture based on abstraction is much more stable than architecture based on detail. In Java, abstraction refers to interfaces or abstract classes, while details are concrete implementation classes. The purpose of using interfaces or abstract classes is to formulate specifications and contracts, without any specific operations, and leave the task of presenting details to their implementation classes.
                At the heart of the dependency inversion principle is interface-oriented programming, and again, let's give an example of how interface-oriented programming is better than implementation-oriented programming. The scene is like this, the mother to the child to read a story, as long as give her a book, she can read a story to the child according to the book.

Example:
Illegal dependency inversion


public class Student { 
  public void read(Book book){ 
    System.out.println(" Students begin reading: "+book.getName()); 
  } 
} 
 
public class Book { 
  public String getName() { 
    return " books "; 
  } 
} 


When students need to read the web page, they need to modify the Student class, which is a very unfriendly design. Let's look at an example of following the dependency inversion principle.


public interface Person { 
  public void read(Reader reader); 
} 
 
public interface Reader { 
  public String getName(); 
} 
 
public class Student implements Person{ 
  @Override 
  public void read(Reader reader) { 
    System.out.println(" Students begin reading: "+reader.getName()); 
  } 
} 
 
public class Book implements Reader { 
  public String getName() { 
    return " books "; 
  } 
} 
 
public class Website implements Reader { 
  public String getName() { 
    return " Web page "; 
  } 
} 
 
public class Test { 
  public static void main(String[] args) { 
    Person student = new Student(); 
    student.read(new Book()); 
    student.read(new Website()); 
  } 
} 


In the read method we use the interface as an argument.

Conclusion:
1. It is better for each class to have an interface or an abstract class, or both.
2. It is best to declare an interface or an abstract class.
3. Follow the Richter substitution principle when inheriting.


Related articles: