Solid principle of software design pattern

Time:2022-4-23

Solid principle of software design pattern

By: guest granting QQ: 1033553122

#Single responsibility principle (SRP)

Definition: any software module is only responsible for a certain type of actors

Note: in most cases, the “software module” here can be simply defined as a source code file, a class, a group of closely related functions and data structures

 

#Opening and closing principle (OCP)

Definition: software entities should be open to extensions and closed to modifications

explain: the “software entity” here includes modules, classes, interfaces, methods, etc

The original intention of opening and closing is to tell us that when the requirements of the application change, the new requirements can be met by adding new code without modifying the original source code or binary code of the software entity, that is to sayA well-designed computer system should be easily extended without modification, which is the fundamental purpose of the architecture. If a small extension of the original requirements requires a significant modification of the original software system, the architecture design of the system is obviously a failure.

 

In languages such as Java and C + +, the opening and closing principle can be realized through “abstract constraints and encapsulation changes”, that is, a relatively stable abstraction layer is defined for software entities through interfaces or abstract classes, and the same variables are encapsulated in the same specific implementation classes. Because the abstraction has good flexibility and wide adaptability, as long as the abstraction is reasonable, the stability of the software architecture can be basically maintained. The changeable details in the software can be extended from the implementation class derived from the abstraction. When the software needs to change, you only need to re derive an implementation class to extend according to the requirements.

In Python, everything is an object and can point to any type. Therefore, you can implement similar interfaces without defining interfaces.

 

#Richter substitution principle (LSP)

The first definition: if there is object O2 of type T for each object O1 of type s, so that the behavior of program P does not change when all objects O1 are replaced with O2, then type s is a subtype of type T.

The second definition: all references to the base class must be able to use the objects of its subclasses transparently.

 

The first definition is the most authentic definition, while the second definition is the most clear. Generally speaking, as long as the parent can appear, the subclass can appear, and replacing it with a subclass will not produce any errors or exceptions. The user may not need to know whether it is a parent or a subclass at all. However, the reverse is not possible. Where there are subclasses, the parent class may not be able to adapt

 

Richter’s substitution principle is the cornerstone of inheritance and reuse. Only when the derived class can replace the base class and the function of the software unit is not affected, that is, no matter how the base class changes, the subclass will not be affected, then the base class can be truly reused

Because of the intrusiveness brought by inheritance, it increases the coupling and reduces the code flexibility. If the parent class modifies the code, the subclass will also be affected. To make the program comply with the Richter replacement principle, the following points must be observed when implementing inheritance:

1) Subclasses must implement the abstract methods of the parent class, but must not override (override) the non abstract (implemented) methods of the parent class.

2) When the subclass overrides or implements the method of the parent class, the formal parameters of the method are more relaxed than the input parameters of the parent class method.

3) When the method of the subclass implements the abstract method of the parent class, the return value of the method is more strict than that of the parent class.

4) If the requirements cannot be met by following the above points, you can consider adding your own unique methods to the subclass.

 

 

#Interface isolation principle (ISP)

definition:

1. The client should not rely on interfaces that it does not need

2. Dependencies between classes should be based on the smallest interface.

 

The simple understanding is not to put many methods in an interface, which will make this class very bulky. Taking java interface class as an example, all non Abstract subclasses that inherit the interface must implement all methods owned by the interface class. Therefore, when these subclasses only need some methods in the interface class, they still need to implement interface methods that are meaningless to them. Therefore, the interface should be as detailed as possible, An interface corresponds to a functional module. At the same time, there should be as few methods in the interface as possible to make the interface more flexible and lightweight. However, it should be noted that splitting shouldModeration. It is a fact that refining the interface can improve the flexibility of program design, but if it is too small, it will cause too many interfaces and complicate the design. So we must be moderate.

 

Although the principle of interface isolation and the principle of single responsibility are very similar, there are obvious differences between the two principles. The principle of single responsibility is the division of business logic, focusing on responsibilities. The principle of interface isolation is based on the consideration of interface design.

 

 

#Dependency reversal principle (DIP)

The dependency inversion principle is called the dependency inversion principle,

definition:

1) High level strategic code should not rely on code that implements the underlying details

2) Abstract should not depend on details, details should depend on abstraction

 

explain:

1. What is “high level” and what is “detail”?

For a system, business logic is high-level, and others are details. Business logic only includes use cases and business entities, and does not include any framework, storage (database), other systems and other parts. It is pure. Other details, including framework, database and message queue, are details. Business logic should not rely on any details. The implementation of details can be replaced arbitrarily without affecting the business logic.

 

The dependency inversion principle is based on the design concept that abstract things are much more stable than the variability of details. The architecture based on abstraction is much more stable than that based on detail, and its central idea is interface oriented programming

This principle tells us that if we want to design a flexible system, we should refer to stable abstract types rather than specific implementations in the dependencies at the source code level. In particular, we should not create derived classes on specific implementation classes or overwrite functions containing specific implementations. In Java, abstraction mostly refers to interfaces or abstract classes. The purpose of using interfaces or abstract classes is to formulate specifications without involving any specific operations, and hand over the task of showing details to their implementation classes.

Obviously, it is unrealistic to strictly implement this design principle as a golden rule, because in the process of actually constructing the system, it is inevitable to rely on some specific implementations, such as the string class of Java. It is unrealistic for us to force it into abstract classes. Similar to the string class, which is a very stable class and module, you don’t need to consider it. You need to pay more attention to the specific implementation modules that often change.

 

In Python, dependency inversion can be easily implemented without abstracting classes

 

Example: music toy player simulation program, which is required to play the sounds of various animals.

At first, the requirements of this toy were relatively simple. At first, it was only required to play an animal sound, bird song

 

Bird.java

publicclass Bird{

publicvoid call(){

System.out.println(“bird call”);

}

}

 

ToyPlayer.java

publicclass ToyPlayer{

publicvoidPlay (bird) {# the input parameter here refers to the specific implementation class

bird.call();

}

}

 

Entry.java

publicclass Entry {

publicstaticvoid main(String[] args){

ToyPlayer player = new ToyPlayer();

Bird bird = new Bird();

player.play(bird);

}

}

 

As mentioned above, the above code does not comply with the dependency inversion principle. The player class depends on specific animal classes (implementation classes). When the requirements change, they may not be able to meet the requirements. For example, if you need to add other animal sounds to the toy, such as dog barking, you need to change the program at this time.

Improved version

Animal.java

interface Animal{

publicvoid call();

}

 

Bird.java

publicclass Bird implements Animal{

publicvoid call(){

System.out.println(“bird call”);

}

}

 

Dog.java

publicclass Dog implements Animal{

publicvoid call(){

System.out.println(“dog call”);

}

}

 

 

ToyPlayer.java

publicclass ToyPlayer{

publicvoidPlay (animal) {# note that the parameter type is replaced here — replace the concrete class type bird with the abstract class type animal

animal.call();

}

}

 

 

Entry.java

publicclass Entry {

publicstaticvoid main(String[] args){

ToyPlayer player = new ToyPlayer();

Bird bird = new Bird();

player.play(bird);

 

Dog dog = new Dog();

player.play(dog);

}

}

 

 

 

 

 

 

Recommended Today

Network counting experiment I Division VLAN

Experiment 1  vlanCreation and division of 1、 Experiment purpose: 1. Understand the working principle of VLAN; 2. Learn the method of dividing VLANs based on ports; 3. Understand the communication between the same VLANs across switches; 4. Further learn the configuration commands of switch ports. 2、 Experimental principle: VLAN (virtual local area network), that is, […]