Design Principle - Dependency Inversion Principle

Definition: High-level modules should not depend on low-level modules, both should depend on their abstractions; abstractions should not depend on details; details should depend on abstractions.

The origin of the problem: Class A directly depends on class B. If you want to change class A to depend on class C, you must modify the code of class A to achieve it. In this scenario, class A is generally a high-level module responsible for complex business logic; class B and class C are low-level modules responsible for basic atomic operations; if class A is modified, it will bring unnecessary risks to the program.

Solution: Modify class A to depend on interface I, class B and class C implement interface I respectively, and class A indirectly contacts class B or class C through interface I, which will greatly reduce the probability of modifying class A.

         The Dependency Inversion Principle is based on the fact that abstract things are much more stable than details are variable. Architectures built on abstraction are much more stable than architectures built on details. In java, abstract refers to an interface or abstract class, and details are specific implementation classes. The purpose of using interfaces or abstract classes is to formulate specifications and contracts, without involving any specific operations, and leave the task of showing 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 how interface-oriented programming is better than implementation-oriented programming. The scene is like this, the mother tells the story to the child, as long as she gives her a book, she can tell the story to the child according to the book. code show as below:

class Book{  
    public String getContent(){  
        return "A long, long time ago there was an Arabic story...";  
    }  
}  
  
class Mother{  
    public void narrate(Book book){  
        System.out.println("Mom started telling a story");  
        System.out.println(book.getContent());  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        Mother mother = new Mother();  
        mother.narrate(new Book());  
    }  
}  

 operation result:

  Mom started telling stories
  long, long ago there was an Arabian story...

        It works well, if one day, the demand becomes this: not a book but a newspaper, let the mother tell the story in the newspaper, the code of the newspaper is as follows:

class Newspaper{  
    public String getContent(){  
        return "Lin Jeremy led the Knicks to beat the Lakers 38+7...";  
    }  
}  

 The Mother class has a dependency relationship with the interface IReader, while Book and Newspaper belong to the category of reading materials. They each implement the IReader interface, which conforms to the principle of dependency inversion. The code is modified as follows:

class Newspaper implements IReader {  
    public String getContent(){  
        return "Lin Jeremy 17+9 to help the Knicks beat the Eagles...";  
    }  
}  
class Book implements IReader{  
    public String getContent(){  
        return "A long, long time ago there was an Arabic story...";  
    }  
}  
  
class Mother{  
    public void narrate(IReader reader){  
        System.out.println("Mom started telling a story");  
        System.out.println(reader.getContent());  
    }  
}  
  
public class Client{  
    public static void main(String[] args){  
        Mother mother = new Mother();  
        mother.narrate(new Book());  
        mother.narrate(new Newspaper());  
    }  
}  

 operation result:

Mom started telling stories
long, long ago there was an Arabian story...
Mom started to tell a story
Jeremy Lin helped the Knicks beat the Eagles with 17+9...

    After this modification, no matter how the Client class is extended in the future, there is no need to modify the Mother class. This is just a simple example. In practice, the Mother class representing the high-level module will be responsible for completing the main business logic. Once it needs to be modified, there is a great risk of introducing errors. Therefore, following the dependency inversion principle can reduce the coupling between classes, improve the stability of the system, and reduce the risk caused by modifying the program.

    The use of the dependency inversion principle brings great convenience to the parallel development of multiple people. For example, in the above example, when the Mother class is directly coupled with the Book class, the Mother class must wait for the Book class to be encoded before coding, because the Mother class depends on in the Book class. The modified program can be started at the same time without affecting each other, because Mother has nothing to do with the Book class. The more people involved in collaborative development and the larger the project, the more important it is to adopt the dependency-induced principle. The now popular TDD development model is the most successful application of the Dependency Inversion Principle.

         There are three ways to transfer dependencies. The method used in the above example is interface transfer. There are also two transfer methods: constructor transfer and setter method transfer. I believe that those who have used the Spring framework will not be unfamiliar with the transfer method of dependencies. .
In actual programming, we generally need to do the following three points:

  • Low-level modules should try to have abstract classes or interfaces, or both.
  • Variables should be declared as abstract classes or interfaces as much as possible.
  • Follow the Liskov substitution principle when using inheritance.

        The core of the Dependency Inversion Principle is to ask us to interface-oriented programming , and to understand interface-oriented programming, we also understand Dependency Inversion.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326500738&siteId=291194637