Design mode_ 03 six design principles
Opening and closing principle
It is open to extensions and closed to modifications.
Implemented through interfaces and abstract classes.
Code implementation:
class Abstract_father { public: virtual void func() = 0; }; class son1 : Abstract_father { public: void func() { cout << "son1" << endl; } };
Richter substitution principle
Where any base class can appear, subclasses must appear.
Subclasses can extend the functions of the parent class, but cannot change the original functions of the parent class (try not to override the methods of the parent class). When polymorphism is used very frequently, the probability of program error is very high.
Dependence Inversion Principle
High level modules should not rely on lower level classes.
Both should rely on abstraction. Abstraction should not rely on details. Details should rely on abstraction. Programming abstractions.
Interface isolation principle
The client should not be forced to rely on methods it does not use.
The dependence of one class on another should be based on the smallest interface.
Original case:
class Abstract_father { public: virtual void func1() = 0; virtual void func2() = 0; }; class son1 : Abstract_father { public: void func1() { cout << "son1" << endl; } void func2() {} //Methods not required };
Improvement cases:
class Abstract_father { public: virtual void func1() = 0; }; class Abstract_Mother { public: virtual void func2() = 0; }; class son1 : Abstract_father { public: void func1() { cout << "son1" << endl; } };
Dimitt's law
If two software entities do not need to communicate directly, direct mutual call should not occur, and the call can be forwarded through a third party (intermediary).
class house_searcher { public: string searcherName() { string name = "searcher"; return name; } }; class house_host { public: string hostName() { string name = "host"; return name; } }; //Do not communicate directly, but establish contact through intermediary class agent { private: house_searcher searcher; house_host host; public: void getName() { cout << searcher.searcherName() << ' ' << host.hostName() << endl; } };
Synthetic Reuse Principle
Try to use the combination or aggregation relationship first, and then consider the inheritance relationship.
Class reuse is divided into inheritance reuse and composition reuse.
Disadvantages of inheritance and reuse:
1. The inheritance relationship destroys the encapsulation characteristics of the parent class. Subclasses can override methods of the parent class.
2. High coupling between subclass and parent. The parent class needs to be modified, and the child class needs to be modified accordingly.
3. It limits the flexibility of reuse. Inheritance relationships cannot be modified at run time.
Advantages of synthetic multiplexing:
1. Maintain the encapsulation of the class.
2. Low coupling between objects.
3. High flexibility of reuse. New objects can dynamically reference objects of the same type as member objects.
Inheritance reuse code:
class Car { public: virtual void show() { cout << "car" << endl; } }; class electricCar : Car { public: virtual void show() { cout << "electriCar" << endl; } }; class whiteElectricCar : electricCar { public: virtual void show() { cout << "whiteElectricCar" << endl; } }; class redElectricCar : electricCar { public: virtual void show() { cout << "redElectricCar" << endl; } };
Composite reuse code:
class Color { public: void show() { cout << "red "; } }; class Car { protected: Color color; public: virtual void show() { Car::color.show(); cout << "Car" << endl; } }; class electricCar : Car { public: virtual void show() { Car::color.show(); cout << "electriCar" << endl; } };