1. single responsibility principle (SRP)**
Definition: in terms of a class, there should be only one reason for it to change. It is difficult to understand the meaning of this definition. In general, we should not let a class take on too much responsibility. If a class has too many responsibilities, it is equivalent to coupling these responsibilities. The change of a responsibility may weaken or inhibit the ability of the class to fulfill other responsibilities. This coupling can lead to fragile design, and when changes occur, the design will be damaged. For example, I often see some Android developers write bean files in activity and network data processing. If there is a list, adapter is also written in activity. Ask them why there is no reason for them to find them except for good search. It is not better to split them into other classes. If the activity is too bloated, it is obviously not good. If we want to modify bean file, Network processing and adapter need to modify this activity, which will cause too many reasons for this activity change. We will also have a headache in version maintenance. It also goes against the definition “in terms of a class, there should be only one reason for it to change.”. Of course, if you want to argue, this pattern can cause a lot of debate, but remember that you write code not just for you but for others.
2. open and closed principle (ASD)**
Definition: classes, modules, functions, etc. should be extensible, but not modifiable. Open closure has two meanings: one is open for expansion and the other is closed for modification. For development, the requirements must change, but as soon as the new requirements come, it is obvious that we should change the class again. Therefore, we should ensure relative stability as much as possible when designing the requirements, and try to modify the requirements by expanding the new code, rather than modifying the original code. Suppose we want to implement a list, at first, only query function. If the product needs to add function, and add deletion function in a few days, most people’s approach is to write a method and then control the method by passing in different values to realize different functions, but if we want to add new functions, we have to modify our method. The solution by using the development closure principle is to add an abstract function class, and add and delete and query the sub class of this abstract function class. If we add functions again, you will find that we don’t need to modify the original class, only add a subclass of functional class to realize the function class.
3. principle of Richter substitution (LSP)**
Definition: all reference base class (parent class) must be able to use the object of its subclass transparently * * the principle of Richter substitution tells us that in software, a base class object is replaced with its subclass object, and the program will not generate any errors and exceptions, which in turn will not be true. If a software entity uses a subclass object, Then it doesn’t have to be able to use base class objects. The principle of Richter substitution is one of the important ways to realize the open and close principle. Because the subclass objects can be used where the base class objects are used, the basic class type is used to define the object as much as possible in the program. At the time of running, the subclass type is determined and the subclass object is used to replace the parent object. In the use of the principle of Richter substitution, the following problems should be noted:
All methods of a subclass must be declared in the parent class, or the subclass must implement all the methods declared in the parent class. According to the principle of Richter substitution, in order to ensure the system extensibility, the parent class is usually used for definition in the program. If a method only exists in the subclass and does not provide corresponding declaration in the parent class, it cannot be used in the object defined by the parent class.
When we use the principle of Richter substitution, we try to design the parent class as abstract class or interface, let the subclass inherit the parent class or implement the parent interface, and realize the method declared in the parent class. When running, the subclass instance replaces the parent instance, we can easily expand the system function without modifying the code of the original subclass, Adding new features can be achieved by adding a new subclass. The principle of substitution of Richter is one of the concrete means to realize the open and close principle.
In Java language, in the compilation phase, the java compiler will check whether a program conforms to the principle of Richter substitution. This is a syntax independent inspection, but the inspection of java compiler has limitations.
4. dependence on Inversion Principle (DIP)**
Definition: high level modules should not rely on low-level modules, both of which should rely on abstraction. Abstraction should not depend on detail, detail should depend on abstraction** In Java, abstraction refers to the interface or abstract class, both of which cannot be instantiated directly; Detail is the implementation class, the implementation interface or inheritance of abstract classes, which is the details, that is, the object generated by the keyword new. High level module is the calling end, and the lower level module is the concrete implementation class. The expression of dependency inversion principle in Java is that: the module does not directly depend on each other through abstraction, and its dependency is generated through interface or abstract class. If the class and class depend on the details directly, they will be coupled directly. When modifying, the code of the dependency will be modified simultaneously, which limits the scalability.
5. Dimitri principle (LOD)**
Definition: a software entity should interact with other entities as little as possible** Also known as the principle of minimum knowledge. If a system conforms to the Dimitri rule, when one of the modules is modified, it will affect other modules as little as possible, and the expansion will be relatively easy. This is the limitation of communication between software entities. Dimit rule requires that the width and depth of communication between software entities be limited. The Dimitri rule can reduce the coupling degree of the system and keep the loose coupling relationship between classes. Demeter rule requires that we design the system, we should minimize the interaction between objects. If there is no direct communication between two objects, then the two objects should not have any direct interaction. If one of the objects needs to call one method of another object, we can forward the call through a third party. In short, it is to reduce the coupling degree between existing objects by introducing a reasonable third party. When applying Dimitri rule to system design, we should pay attention to the following points: in the division of classes, we should try to create loose coupling classes. The lower the coupling degree between classes, the more beneficial it is to reuse. Once a class in loose coupling is modified, it will not cause too much wave and for the associated class; In the structure design of class, every class should reduce the access rights of its member variables and member functions; In the design of class, as long as possible, a type should be designed as a invariant class; In references to other classes, one object should be referenced to other objects to a minimum.
6. interface isolation principle (ISP)**
Definition: one class’s dependence on another should be based on the smallest interface** Establish a single interface, do not establish a large and bloated interface, refine the interface as much as possible, and minimize the methods in the interface. That is, we need to establish a dedicated interface for each class, rather than trying to build a huge interface for all classes that rely on it to call. When the interface is constrained by the principle of interface isolation, the following points shall be noted:
The interface is as small as possible, but it should be limited. Refinement of the interface can improve the flexibility of the program design, but if it is too small, it will cause too many interfaces and make the design complex. So be moderate.
Custom services for classes that depend on interfaces are exposed to only the methods it needs for the calling class, and the methods it does not need are hidden. Only by focusing on providing customized services to a module can minimal dependencies be established.
Improve cohesion and reduce external interaction. Make the interface do the most in the least way.
These six principles can make our application iterative maintenance more convenient and easy to deal with, and make our software more flexible. In the following articles, I will introduce you to other design patterns.