3. Dependency Inversion principle (dependence inversion Principle,dip)
3.1 definition
(1) to rely on abstraction , do not rely on specific implementation classes . The simple thing is to program the abstraction (or interface) and not to rely on the implementation to program it, thus reducing the coupling between the customer and the implementation module. Contains 3 levels of meaning:
① high-level modules should not rely on low-layer modules, both should be dependent on the abstract
② abstraction should not depend on details
③ details should be dependent on abstraction
(2) What are "high-rise modules" and "low-level modules"
① "Low-level module": Each logical implementation is composed of atomic logic, the indivisible atomic logic is the low-level module. General and specific implementation-related.
② "High-level modules": Atomic logic reassembly is a high-level module, generally related to business logic. such as clients.
(3) What is "upside down"
① "Relying on positive": is the dependency between classes is a real implementation of the dependency between classes, that is, the implementation of programming, which conforms to the normal thinking of people. If we drive a Mercedes Benz is dependent on the Mercedes-Benz, the use of laptops directly rely on notebook computers.
② "Dependency inversion": programming is to abstract the real world things, and then we based on the needs of the system design to produce a dependency on the abstract, instead of people's traditional thinking of the dependence between things, called "inverted."
3.2 Dependency Implementation problems and improvements in programming
(1) driver can only drive Mercedes-Benz Cars!
"Programming experiments" drivers can only watch Mercedes cars
//Object-oriented design principle: Dip dependency Inversion principle//drivers can only drive Mercedes-Benz-depending on the implementation#include<stdio.h>//Mercedes Benz Car Classclassbenz{ Public: voidrun () {printf ("Benz runing...\n"); }};//Driver Classclassdriver{ Public: //the driver class is not dependent on abstraction, but relies on specific car Benz,//cause the driver can only drive Mercedes-Benz, can not open other car embarrassment! voidDrive (benz&Benz) {Benz.run (); } };intMain () {Driver Zhangsan; Benz Benz; //Zhang San drive Mercedes BenzZhangsan.drive (Benz);//parameter is Benz type, Zhang San will only drive Mercedes! return 0;}
(2) Solution-- introducing dependency inversion!
① the dependency inversion principle through the coupling between classes by the Idriver and icar two interfaces
② Car provides the Run method. The driver's function is to drive a car, which must be achieved by driving. When adding a car class, as long as the car realizes the Icar interface, the driver can open.
③client is a high-level business logic, and its dependence on the lower layer is based on abstraction.
"Programming experiments" drivers can drive all kinds of cars
//Object-oriented design principle: Dip dependency Inversion principle//drivers can drive any car--dependent on abstraction/interface#include<stdio.h>//Automotive Interfaceclassicar{ Public: Virtual voidRun () =0;};//Mercedes Benz Car ClassclassBenz: Publicicar{ Public: voidRun () {printf ("Benz runing...\n");}};//BMW Car ClassclassBWM: Publicicar{ Public: voidRun () {printf ("BWM runing...\n");}};//Driver Interfaceclassidriver{ Public: //the driver should be driving the car . Virtual voidDrive (icar& car) =0;//Dependency Interface};//Driver ClassclassDriver: Publicidriver{ Public: voidDrive (icar& car)//implementing Interfaces{car.run (); }};intMain () {Driver Zhangsan; Benz Benz; BWM BWM; //Zhang San drive Mercedes Benzzhangsan.drive (Benz); //Zhang San Drive BMWzhangsan.drive (BWM); return 0;}
3.3 3 ways to rely (see Chapter 1th)
(1) Constructor pass dependent object
(2) Setter method passed on object
(3) Declaring dependent objects via interfaces (e.g., programming experiment 2)
3.4 Best Practices
(1) Each class has an interface or abstract class as much as possible, or both, which is the basic requirement of dependency inversion, and it is possible to rely on inversion for abstraction.
(2) When declaring a variable, use the interface or abstract class as much as possible, instantiate and use the specific class
(3) No class should be derived from a specific class (or should not exceed two layers when inheriting from a specific class)
(4) Try not to overwrite the method that the base class has already implemented.
(5) The sub-class is designed in conjunction with the Richter replacement principle. So that the implementation of the class can accurately implement business logic and does not violate the LSP principle.
2nd. Object-oriented design principles (SOLID): 3_ dependency Inversion principle