Six principles of design patterns (3) -- six principles of dependency inversion and Design Patterns
Definition:
High-level modules should not depend on low-level modules. Both of them should depend on abstract interfaces. Abstract interfaces should not depend on specific implementations. The specific implementation depends on the abstract interface. The dependency Inversion Principle is called Dependence Inversion Principle (DIP for short.
Problem:
Class A directly depends on Class B. To change Class A to dependent Class C, you must modify the code of Class. 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 brings unnecessary risks to the program.
Solution:
Change Class A to dependent interface I. class B and class C implement interface I. Class A indirectly associates with Class B or Class C through interface I, this greatly reduces the chance of modifying Class.
The dependency inversion principle can reduce inter-class coupling, improve system stability, reduce risks caused by parallel development, and improve code readability and maintainability. The core of the dependency inversion principle is interface-oriented programming. After understanding interface-oriented programming, the dependency inversion principle is also understood. The following is an example of a driver driving:
There is a Mercedes-Benz, which can Run in the Run mode. The driver class has a Drive method. The code for drivers and Mercedes-Benz is as follows:
/// <Summary> /// Mercedes-Benz class /// </summary> public class Benz {// Run public void Run () {Console. writeLine ("the Mercedes-Benz starts running... ") ;}/// <summary> // Driver class // </summary> public class Driver {public void Drive (Benz benz) {benz. run ();}}
The main function driver James starts the Mercedes-Benz. The Code is as follows:
Class Client {static void Main (string [] args) {// var benz = new Benz (); // Driver James var xiaoming = new Driver (); // xiaoming Kai-Benz xiaoming. drive (benz); Console. readKey ();}}
The above scenario enables drivers to drive a car, but the demand for actual business is constantly changing. Technically, "changes are really effective". Only in the "changes" process can we know whether our design or programs are loosely coupled. In the above example, we need to add some requirements: The driver will make a carriage return. To complete this operation, you must first have a BMW type, as shown below:
/// <Summary> /// Bmw type /// </summary> public class Bmw {// Run public void Run () {Console. writeLine ("BMW started running... ");}}
Despite the use of BMW cars, drivers have a way to drive a carriage. You may say that if you have a wooden tree, you can add the method of the kaibao carriage! This solved the problem for a while, but what about Ferrari and Bentley? Therefore, there is a problem in our design: There is a tight coupling relationship between the driver and the Mercedes-Benz. The result is that the maintainability of the system is greatly reduced and the readability is reduced, two similar classes need to read two files, which is obviously not desirable. Stability: solid and robust is stable. Here, we only need to modify the driver class when adding a car class. This is not stability, it is variable. The change of the dependent person actually causes the dependent person to bear the cost of the change. Who will bear the dependency!
In actual project development, the risks caused by parallel development should be minimized. The biggest risk of parallel development is the spread of risks. It was originally a program error or exception that gradually affected a function, a module, and even destroyed the entire project. Because a team has dozens or even hundreds of developers, each person is responsible for different functional modules, A is responsible for the construction of the automobile class, and B is responsible for the construction of the driver class. If a is not complete, B cannot write code completely. Without the car class, the compiler won't let you pass it! Can the Driver class be compiled without the Benz class? Let alone unit test! This type of dependency is not allowed in actual development. In other words, such development can only be modified one by one, and each modification may be a trigger. In today's large and medium-sized projects, this model is completely incompetent. A project is the result of collaboration among a team. It is impossible for a person to understand all the business and technologies, to collaborate, parallel development is required. To achieve parallel development, project dependencies between modules must be solved. Then, the principle of dependency inversion becomes grand.
The core of the dependency inversion principle is the interface. Below we define two interfaces for the vehicle and the driver: ICar and IDriver. The Code is as follows:
/// <Summary> /// vehicle interface /// </summary> public interface ICar {void Run ();} /// <summary> /// Driver interface /// </summary> public interface IDriver {void Drive (ICar car );}
Then let the drivers and cars (BMW and Mercedes) defined above inherit their own interfaces. The Code is as follows:
/// <Summary> /// Mercedes-Benz class /// </summary> public class Benz: ICar {// Run public void Run () {Console. writeLine ("the Mercedes-Benz starts running... ") ;}//< summary> /// Bmw class /// </summary> public class Bmw: ICar {// Bmw running public void Run () {Console. writeLine ("BMW started running... ") ;}/// <summary> /// Driver class // </summary> public class Driver: IDriver {public void Drive (ICar car) {car. run ();}}
The structure of the class is as follows:
When developing and implementing business requirements, we should keep in mind that abstraction does not depend on details. Here, the interfaces of cars and drivers do not depend on the details (specific implementation classes). We can see that this is about to understand the Dependency inversion principle.
The dependency inversion principle is a guiding ideology. It makes the implementation of various classes or modules independent of each other through abstraction (interfaces or abstract classes) without affecting each other, and implements loose coupling between modules, to better use this principle, we need to use it in actual projects as follows:
- Every class should have interfaces, abstract classes, and both as much as possible, and should not be overly reliant on the inverted principle.
- The display type of variables should be an interface or abstract class.
- Do not derive any class from a specific class.
- Try not to override the methods of the base class.
- Use in combination with the Lee's replacement principle
The dependency inversion principle is the most difficult principle to implement in the six design principles. It is an important way to implement the open and closed principles. If the Dependency inversion principle is not implemented, do not consider opening up to expansion, disable modification. In the project, you only need to remember to be "interface-oriented programming" and basically grasp the core of the dependency reversal principle. By the way, the actual project production and profit are the top priorities. Therefore, the principle of the design model only provides the guiding ideology. We should not take the initiative to violate it, but we have to violate the actual situation, otherwise, even if the design is so good and the architecture is perfect, this is all nonsense. Your boss is not happy once the expected duration or project is lost, and then you will be unhappy...
(Java) in the design pattern, "Dependency inversion principle" (dependency abstraction, not dependency on specific classes)
Agree that a simple combination like this is a reflection of dependency. The so-called Dependency inversion means that the dependent B is not obtained directly through B B = new B ();, but first new in the factory, when does A need to use it, just go to the factory to retrieve it.
What are the three elements of object-oriented, five principles and six viewpoints?
Three elements of object-oriented
Encapsulation)
Inheritance)
Polymorphism)
Five Principles of object-oriented
Single Responsibility Principle (SRP)
Open-Close principle (OCP)
Liskov replacement principle (LSP)
Dependency inversion principle (DIP)
Interface isolation principle (ISP)
Object-oriented six Viewpoints
Reuse (Reusibility)
Extensibility)
Separation)
Change)
Simplicity)
Coherance)
That's all. If you have any questions, continue.