Solid principle I understand

Source: Internet
Author: User

S.o.l. I. dIt is the abbreviation of several important coding principles (programming priciple) in Object-Oriented Design (OOD) and Object-Oriented Programming (OOP.

Object-Oriented Design Principles
SRP The single Responsibility Principle Single Responsibility Principle
OCP The open closed Principle Open and closed Principle
LSP The liskov substitution principle Rys replacement principle
ISP The interface segregation principle Interface separation principle
Dip The dependency inversion principle Dependency inversion principle

I. Single Responsibility Principle (SRP)

From the object-oriented perspective, this principle is: "There should never be more than one cause of class changes. "Or" one class has only one responsibility ". This does not seem easy to understand, especially "there will never be more than one cause of class changes. "This sentence is even more confusing.

We usually say "low coupling, high cohesion ". In my opinion, the "single responsibility" here is what we usually call "high cohesion", that isA class can only fulfill its responsibilities., Cannot shirk responsibility, nor be more arrogant, cannot become omnipotent God class. If your team implements loose "collective ownership of code", many people modify (maintain) the same class at the same time during the coding process, and the communication between members is not timely enough, if it takes a long time to take the initiative and smooth flow, it is very likely that there will be a "too many responsibilities" God class. At this time, refining the base class/interface and refining class refactoring will help us eliminate or reduce this design odor.

Let's look at an example:

This is a class structure that violates the "single responsibility principle.
Here, the rectangle class does the following two things:

  • Calculates the rectangular area;
  • Draw a rectangle on the interface (drawing device;

In addition, two applications use the rectangle class:

  • The computational geometry application uses this class to calculate the area;
  • The graphical application uses this class to draw rectangles on the interface;

This violates SRP (single responsibility principle ). Because the rectangle class does two things, it calculates the area in one method, and returns a GUI that represents the rectangle in another method. This brings about some interesting issues: the GUI must be included in the computing ry application. That is, when developing ry applications, we must reference the GUI library. Changes in the rectangle class in graphics applications may lead to changes in the computing ry application, compilation and testing, and vice versa. So how can we make changes to conform to the single responsibility principle?

The answer is: Split! Split responsibilities into two different classes, for example:

  • Rectangle: This class should only define the area () method;
  • Rectangleui: This class should inherit the rectangle class and define the draw () method.

Ii. Open and closed principle (OCP)

From the perspective of object-oriented design, this principle can be understood as follows: "software entities (classes, modules, functions, etc.) should be open to extensions and closed to modifications. "In general, it means that you (or class customers) should be able to expand the behavior of this class without modifying a class. In Ood, opening to expansion means that the behavior of classes or modules can be changed. When demand changes, we can change modules in new and different ways, or meet the requirements in the new application.

That is to say, it is open to extensions and closed to modifications. We generally say that when adding a function to the system, we should only add new code, but try to modify the original code as little as possible. In my opinion, this is the result of following the open and closed principle. I once saw such a sentence on the Internet: "Where is the change and where is the encapsulation ". In fact, we need to encapsulate the changes in the system, that is, to close the changes. At the same time, in order to cope with the expansion of system requirements (functions), it is necessary to abstract!

Here abstraction is the key. The State mode and Strategy Mode in design patterns are the best embodiment of this principle.

For example:

Class structure diagram that violates the open and closed principle.

The client code is directly oriented to the specific implementation programming of the server, which lacks flexibility. In this way, if the server is replaced by another server for some reason, the client must modify or replace the code that calls the server. This is actually the design smell of "implementation-oriented programming!

So how can we get a correct and flexible design after modification?

The answer is: abstraction! Abstracts an abstract base class for the server code (type) (defines a set of minimum interfaces to fulfill service responsibilities ).

The correct design is as follows:

Class Structure Diagram following the open and closed principle.

Basically, what you abstract is the core content of your system. If you abstract it well, it is likely to add a new server type (Extension) you only need to add a new type (inherited from abstractserver ). Therefore, the code should be abstracted (the abstractserver here) as much as possible. This will allow you to expand abstract things and define a new implementation without modifying any client code. That is, "interface-oriented programming, not implementation-oriented"!

Iii. liskov's replacement principle (LSP)

The liskov's replacement principle means: "subtypes must be able to replace their base types. "Or to put it another way:" the object of the inherited class must be used where the base class is referenced, without having to know it. "This principle is the premise to ensure that inheritance can be correctly used. Generally, we all say that "the combination (Delegation) is preferred instead of inheritance" or"Inheritance can be used only when the relationship is determined as is-.", Because inheritance often leads to" tightly coupled "design.
In the basic object-oriented principle, "inheritance" is usually the relationship of "is. If "Developer" is a "softwareprofessional", the "Developer" class should inherit the "softwareprofessional" class. In class design, the "is a" relationship is very important, but it is easy to get confused, resulting in incorrect inheritance, resulting in incorrect design.

Let's take a look at the most classic example:

Class Structure Diagram following the liskov replacement principle.

Note: The Kingfisher class extends the bird base class and inherits the fly () method.

However, the following class structure diagram has design problems:

Class structure diagram that violates the liskov replacement principle.

Ostrich (Ostrich) is a type of bird, which is beyond doubt inherited from the bird class, which is conceptually correct. But can an ostrich fly? No, this design violates LSP. Because ostrich may not be used in place of bird. Therefore, even if it seems that there is no problem in reality, in class design, ostrich should not inherit from the bird class. Here we should separate a class noflybrid that will not fly from the bird, ostrich should inherit this non-flying bird noflybrid.

Why is LSP so important?

  • Without LSP, class inheritance will be chaotic; if the subclass is passed to the method as a parameter, unknown behavior will occur;
  • If no LSP exists, unit tests applicable to the base class cannot be successfully used for the test subclass;

Iv. Interface separation principle (ISP)

This principle means that "clients should not be forced to rely on interfaces they do not need. "That is,An interface or class should have as few behaviors as possible(So, What is as few as possible? That is, the software system module should be as small as possible to fulfill its own responsibilities.

If an interface contains too many methods, its availability will be reduced. For example, a "Fat interface" that contains useless methods will increase coupling between classes. If a class wants to implement this interface, it needs to implement all the methods, although some of them may be completely useless, so this will introduce unnecessary complexity in the system, reduces code maintainability or robustness.

The interface separation principle ensures that the Implemented interfaces have their common responsibilities and they are clear,Easy to understand and reusable.

The following example shows that the interface should only contain the necessary methods, rather than other methods.If an interface contains too many methods, it should be split through the separation interface.

This is a fat interface that violates the interface separation principle.

Note that the iBIRD Interface contains many bird behaviors, including fly () behavior. if a bird class (such as ostrich) implements this interface, it needs to implement unnecessary fly () behavior (ostrich will not fly ). Therefore, this "Fat interface" should be split into two different interfaces, iBIRD and iflyingbird, while iflyingbird inherits from iBIRD. As shown in:

In this way, reuse becomes very flexible: if a bird does not fly (such as ostrich), it implements the iBIRD interface. If a bird can fly (such as Kingfisher), it implements iflyingbird.

Therefore, if we want to obtain a reusable solution, we should follow the interface separation principle and define the interface as containing only necessary parts,This interface can be reused wherever this interface function is required.

V. Dependency inversion principle (DIP)

This principle means that the high-level module should not depend on the underlying module, and both should depend on its abstraction. It is actually an internal requirement of "interface-oriented programming, not implementing programming.

Let's consider a real-world example to see the benefits of the dependency inversion principle to our software.

Your car is composed of many components, such as engines, wheels, air conditioners, and others, right?

Note: here the car is the high-level module. It relies on the abstract interfaces itoyotaengine and ieighteeninchwheel.

The specific engine teteenhundredccengine belongs to the underlying module and also relies on the abstract interface itoyotaengine;

The specific wheel eighteeninchwheelwithalloy also belongs to the underlying module and also relies on the abstract interface ieighteeninchwheel.

The above car class has two attributes (engine and wheel list ),They are all abstract types (interfaces ). The engine and wheel are pluggable,Because the car can accept any object that implements the declared interface,The car class does not need to be modified.

In addition to the solid principle, there are many other object-oriented principles. For example:

  1. "Combination substitution inheritance": Compared with inheritance, combination is preferred;
  2. "Dummit's Law": This is to say, "The less your class knows about other classes, the better ";
  3. "The principle of joint closure": this is to say "related classes should be packaged together ";
  4. "Stable abstraction principle": "The more stable the class, the more it should be composed of abstract classes ";
Of course, these principles do not exist in isolation, but are closely linked. They follow one or more principles while following one principle. On the contrary, A violation of one of these principles may also violate one or more of them at the same time. The design pattern is the application result of these principles in some specific scenarios. Therefore, we can regard the design pattern as a "Framework" and the OOD principle as a "Specification ". In the process of learning the design pattern, we need to constantly reflect on which or which of the object-oriented design principles is embodied in this pattern. Especially in the process of reconstruction Implementation Mode or reconstruction trend mode, we should consider the differences between code before and after reconstruction based on the solid principle and understand its improvements. I am studying refactoring and pattern, so next I will record my learning experience with examples. Note: take the film from "how to explain to my wife Ood" Translated by: http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.