Seven basic design principles:
abbreviations | The English name | Chinese name | Chinese name |
---|---|---|---|
SRP | Single Responsibility Principle | Single responsibility principle | Each class should focus on doing one thing |
OCP | Open Close Principle | The open closed principle | Open for extension, closed for modification |
LSP | Liskov Substitution Principle | Richter’s substitution principle | The implementation relies on abstraction rather than concrete implementation |
ISP | Interface Segregation Principle | Interface separation principle | The client should be provided with the smallest possible individual interface, rather than a large total interface |
DIP | Dependency Inversion Principle | Dependency inversion principle | The implementation relies on abstraction rather than concrete implementation |
LoD | Law of Demeter (Least Knowledge Principle) | Demeter’s Rule (least Know rule) | Also known as the least knowledge principle, a software entity should interact with as few other entities as possible |
CARP | Composite/Aggregate Reuse Principle CARP | Synthesis/polymerization reuse principle | Use composition/aggregation as much as possible for reuse and inheritance as little as possible. Principle: One class has an object of another class |
Note that the design principles commonly referred to as SOLID (the initials of the table above, from top to bottom) do not contain Demeter’s law, but only the other five
Principle 1: open and close principle
A software entity such as a class, module, or function should be open for extension and closed for modification
Define the interpretation
- Build the framework with abstractions and extend the details with implementations
- New requirements should not be implemented by modifying existing classes, but rather by implementing preabstracted interfaces (or concrete classes inheriting abstract classes)
advantages
The advantage of practicing the open close principle is that you can extend functionality without changing the original code. The expansibility of the program is increased, and the maintenance cost of the program is reduced.
How to practice
In order to best practice the open close principle, it is important at the beginning of the design to figure out which data (or behaviors) in the scenario are fixed (or hard to change) and which are easily changeable. The latter can be abstracted into interfaces or abstract methods so that different requirements can be addressed in the future by creating concrete implementations.
Principle two: Single responsibility principle
A class is allowed to have only one responsibility, that is, only one reason for the change of that class
Define the interpretation
- Changes in class responsibilities are often the cause of class changes: that is, if a class has more than one responsibility, there will be more than one reason for that class to change, making maintenance of that class difficult
- Often in software development, as the requirements continue to increase, it is possible to add some responsibilities to the original class that do not belong to it, thus violating the single responsibility principle. If we find that the current class has more than one responsibility, we should separate out responsibilities that are not really part of the class
- Not only classes, but also functions (methods) follow the single responsibility principle: a function (method) does only one thing. If you find a function (method) with different tasks, you need to separate out the different tasks in the form of another function (method)
advantages
A clear division of responsibilities between classes and methods not only improves the readability of the code, but also substantially reduces the risk of errors, because clear code leaves bugs nowhere to hide and facilitates bug tracking, which in turn reduces maintenance costs
How to practice
In practice, it’s easy to combine different responsibilities, and developers need to be aware of this
Principle three: dependence inversion principle
- Rely on abstraction, not implementation
- Abstractions should not depend on details, details should depend on abstractions
- High-level modules cannot depend on low-level modules; both should depend on abstractions
Define the interpretation
- Program for interfaces, not implementations
- Try not to derive from concrete classes, but instead implement by inheriting abstract classes or implementing interfaces
- The division of high-level module and low-level module can be divided according to the level of decision-making ability. The business layer is naturally placed in the upper module, and the logical layer and data layer are naturally categorized as the bottom layer
advantages
Through abstraction to build the framework, the establishment of class and class association, in order to reduce the coupling between classes. Moreover, the system built by abstraction is more stable, more expansible and easier to maintain than the system built by concrete implementation
How to practice
In the future, when dealing with the interaction of high and low level modules (classes), we should try our best to remove the dependence of the two by abstract means, which can be implemented through interfaces or abstract classes
Principle 4: Interface separation
Multiple specific client interfaces are better than one universal master interface
Define the interpretation
- A client should not rely on interfaces it does not need to implement
- Instead of creating a large and bloated interface, you should refine the interface as much as possible and use as few methods as possible
Note that the granularity of interfaces should not be too small. If the size is too small, the number of interfaces is too large, which complicates the design
advantages
Avoid the method that the same interface contains different kinds of responsibilities, and the interface responsibility division is more clear, in line with the idea of high cohesion and low coupling
How to practice
Because of the redundancy caused by the design of interface methods, the design does not comply with the principle of interface isolation.
When designing interfaces, and especially when adding methods to existing interfaces, we need to carefully consider whether these methods address the same kind of task: if so, they can be put together; If not, you need to split it
Principle 5: Demeter’s Rule
An object should touch as few objects as possible, that is, only those that really need to be touched
Define the interpretation
Also known as the Least Know Principle, a class should communicate only with classes in its member variables, method inputs, and return parameters, and should not introduce other classes (indirect communication)
advantages
Practice of Demeter’s law can well reduce the coupling between classes, reduce the degree of association between classes, and make the collaboration between classes more direct
How to practice
In the future, when designing the interaction between objects, we should try our best to avoid eliciting intermediate objects (classes of other objects need to be imported) : what objects need to be returned directly, reducing the degree of coupling between classes
Principle 6: Richter’s substitution principle
All references to a base class must be able to use objects of its subclasses transparently, that is, subclass objects can replace their parent class objects without the program executing the same
Define the interpretation
In the inheritance system, a subclass can add its own unique methods and implement the abstract methods of the parent class, but cannot override the non-abstract methods of the parent class, otherwise the inheritance relationship is not a correct inheritance relationship.
advantages
It can check the correctness of inheritance and restrain the overflow of inheritance in use
How to practice
Richter’s substitution principle is a test of inheritance relation: to check whether it really conforms to inheritance relation, so as to avoid the abuse of inheritance. Therefore, before using inheritance, it is necessary to repeatedly consider and confirm whether the inheritance relationship is correct, or whether the current inheritance system can support subsequent requirement changes. If not, it is necessary to timely reconstruct and adopt a better way to design the program
Principle 7: Synthesis/polymerization reuse principle
Use composition/aggregation as much as possible for reuse and inheritance as little as possible. Principle: One class has an object of another class
Define the interpretation
Take some existing objects and make them part of the new object. The new object can reuse its existing functions by delegating methods that call the existing object. That is, use synthetic reuse of classes as much as possible, and avoid inheritance as much as possible
advantages
The combination/aggregation reuse principle can make the system more flexible, the degree of coupling between classes is reduced, and the change of one class has less impact on other classes
How to practice
When using inheritance, we should strictly follow the Leighton substitution principle. The effective use of inheritance will help to understand the problem and reduce the complexity, while the abuse of inheritance will increase the difficulty of system construction and maintenance and the complexity of the system. Therefore, we should carefully use inheritance reuse
The seven basic principles of object-oriented design patterns