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