当前位置:网站首页>Solid principle: explanation and examples
Solid principle: explanation and examples
2022-07-02 08:30:00 【J-A】
In object oriented programming ,SOLID yes 5 Abbreviation for an important design principle . First, by the famous software Masters Robert C.Martin (Bob uncle ) stay Design Principles and Design Patterns It is proposed that , later Michael Feathers use SOLID To summarize these five principles .
SOLID Principles make software design Easier to understand 、 Flexible and maintainable . As a software engineer , this 5 There are three principles we must know .
this paper , I will cover these principles , And illustrate with examples how it violates the principle , And how to correct it to meet SOLID principle .
S — Single responsibility principle
In programming , The single responsibility principle means that each module or class should have only one responsibility .
You may have heard such a proverb “ Do a thing and do it well ”, This refers to the principle of single responsibility .

In the article 《Principles of Object Oriented Design》 in ,Bob Uncle defines responsibility as “ The reason for the change ”. And think that there is one and only one reason to change the class or module .
class User
{
void CreatePost(Database db, string postMessage)
{
try
{
db.Add(postMessage);
}
catch (Exception ex)
{
db.LogError("An error occured: ", ex.ToString());
File.WriteAllText("\LocalErrors.txt", ex.ToString());
}
}
}
In the above code example , We noticed that *CreatePost()* Methods have multiple functions , Create a new message , Record the error log in the database and in the local file .
This violates the principle of single responsibility . We try to modify it as follows :
class Post
{
private ErrorLogger errorLogger = new ErrorLogger();
void CreatePost(Database db, string postMessage)
{
try
{
db.Add(postMessage);
}
catch (Exception ex)
{
errorLogger.log(ex.ToString())
}
}
}
class ErrorLogger
{
void log(string error)
{
db.LogError("An error occured: ", error);
File.WriteAllText("\LocalErrors.txt", error);
}
}
By abstracting the error log function , We no longer violate the principle of single responsibility .
Now there is 2 Classes , Each class has a responsibility ; Create mail and record an error log .
O — Open/closed principle
In programming , The open close principle refers to the software object ( class , modular , Function, etc. ) It should be open to extension , Turn off for changes .

If you are familiar with OOP, Then polymorphism should be no stranger . Implement through inheritance or interface , Make an abstract class have multiple subclasses , You can ensure that the code conforms to the opening and closing principle .
This sounds a little confused , So let's take an example , You'll know exactly what I'm talking about .
class Post
{
void CreatePost(Database db, string postMessage)
{
if (postMessage.StartsWith("#"))
{
db.AddAsTag(postMessage);
}
else
{
db.Add(postMessage);
}
}
}
In this code snippet , Whenever a message is written in characters “#“ start , We all need to make some assignments . However , When there are different characters beginning , Code will behave differently , This goes against the principle of opening and closing .
such as , If we want to use “@” start , We have to CreatePost() Add a ‘else if’, This modifies the class .
Inheritance is simply used here to make the code conform to the open and close principle .
class Post
{
void CreatePost(Database db, string postMessage)
{
db.Add(postMessage);
}
}
class TagPost : Post
{
override void CreatePost(Database db, string postMessage)
{
db.AddAsTag(postMessage);
}
}
By using inheritance , rewrite *CreatePost()* Method to create the extended behavior of the message .
Now? , Judge the first character “#” It can be handled elsewhere in the software . The cooler thing is , If we want to change postMessage The way to judge , Can not affect the behavior of the base class .
L — Liskov substitution principle
This principle is probably the most difficult to understand at the first introduction .

In programming , The Richter substitution principle refers to if S yes T Subclasses of , that T Examples of can be used S Instead of .
A more general expression is , Without changing the correctness of the program , A derived class object can replace its base class object in a program .
class Post
{
void CreatePost(Database db, string postMessage)
{
db.Add(postMessage);
}
}
class TagPost : Post
{
override void CreatePost(Database db, string postMessage)
{
db.AddAsTag(postMessage);
}
}
class MentionPost : Post
{
void CreateMentionPost(Database db, string postMessage)
{
string user = postMessage.parseUser();
db.NotifyUser(user);
db.OverrideExistingMention(user, postMessage);
base.CreatePost(db, postMessage);
}
}
class PostHandler
{
private database = new Database();
void HandleNewPosts() {
List<string> newPosts = database.getUnhandledPostsMessages();
foreach (string postMessage in newPosts)
{
Post post;
if (postMessage.StartsWith("#"))
{
post = new TagPost();
}
else if (postMessage.StartsWith("@"))
{
post = new MentionPost();
}
else {
post = new Post();
}
post.CreatePost(database, postMessage);
}
}
}
Because there is no override ,CreatePost() Method in subclass MentionPost Will not play its due role .
Revised as follows :
...
class MentionPost : Post
{
override void CreatePost(Database db, string postMessage)
{
string user = postMessage.parseUser();
NotifyUser(user);
OverrideExistingMention(user, postMessage)
base.CreatePost(db, postMessage);
}
private void NotifyUser(string user)
{
db.NotifyUser(user);
}
private void OverrideExistingMention(string user, string postMessage)
{
db.OverrideExistingMention(user, postMessage);
}
}
...
By refactoring MentionPost class , Can meet the replaceability .
This is just a simple example that does not violate the Richter substitution principle . However , In actual use , This situation can be achieved in many ways and is not easy to identify .
I — Interface segregation principle
This principle is easy to understand , actually , If you are used to using interfaces , There is a high probability that this principle will be used .

In programming , The principle of interface isolation means that customers should not be forced to use methods or functions that are useless to them .
simply , Don't add new methods to existing interfaces to realize new functions . Contrary , You can create new interfaces , If necessary , You can make your class implement multiple interfaces .
interface IPost
{
void CreatePost();
}
interface IPostNew
{
void CreatePost();
void ReadPost();
}
In the above code example , Suppose I already have one IPost Interface , contain CreatePost() Method ; later , I added a new method ReadPost(), This interface has been modified , become IPostNew Interface , This violates the principle of interface isolation . Revised as follows :
interface IPostCreate
{
void CreatePost();
}
interface IPostRead
{
void ReadPost();
}
Once any class needs to implement this 2 A way , This will be achieved at the same time 2 Interface .
D - Dependency inversion principle
Last , Let's take a look D, The last design principle .

In programming , The dependency inversion principle is used to decouple modules in software . This principle is expressed as follows :
- High level modules should not rely on low-level modules , Instead, we should rely on abstraction ;
- Abstraction should not rely on implementation details , Implementation details should rely on abstraction .
In order to follow this principle , We need to use a design pattern called Dependency injection , Typical , Dependency injection takes the constructor of the class as the input parameter .
class Post
{
private ErrorLogger errorLogger = new ErrorLogger();
void CreatePost(Database db, string postMessage)
{
try
{
db.Add(postMessage);
}
catch (Exception ex)
{
errorLogger.log(ex.ToString())
}
}
}
Observe that we are Post Class ErrorLogger example , If we want to use different logs , We need to change Post class , This goes against the principle of dependence inversion . Revised as follows :
class Post
{
private Logger _logger;
public Post(Logger injectedLogger)
{
_logger = injectedLogger;
}
void CreatePost(Database db, string postMessage)
{
try
{
db.Add(postMessage);
}
catch (Exception ex)
{
_logger.log(ex.ToString());
}
}
}
By using dependency injection , We no longer rely on Post Class to define the log of the specified type .
OK, After introducing so many , I have also roughly understood these principles . These principles are different , At the same time, they are also connected .

- The principle of single responsibility is SOLID The basis of all principles and ideas for solving problems .
- The principle of opening and closing is the principle that directly guarantees the quality of code , To solve the vulnerability of design 、 Ossification 、 Difficult to read 、 Difficult to reuse , The key to applying the opening and closing principle is how “ abstract ”.
- The Richter substitution principle ensures that subclasses and superclasses are “is a” The relationship between , To help realize the opening and closing principle . The principle is in use , Extend the object-oriented perspective “is a” It's about behavior , And the correctness of the model is not inherent , It is embodied by its client program .
- The interface isolation principle provides a solution , Without violating the Richter replacement principle , How to realize the open close principle . At the same time, the idea of interface isolation also embodies the principle of single responsibility .
- Dependency inversion principle is the watershed between procedural design and object-oriented design , Through appropriate abstraction , Make high-level modules as reusable and testable as low-level modules . It's also used to guide interface isolation principles .
Reference resources
【2】Single Responsibility Principle in C++
【4】Open Closed Principle in C++
【5】 Opening and closing principle
【6】Liskov’s Substitution Principle in C++
【7】 Richter's principle of substitution
【8】Interface Segregation Principle in C++
【9】 Interface isolation principle
【10】Dependency Inversion Principle in C++
【11】 The principle of Dependence Inversion
That’s it!If you have any questions or feedback, please feel free to comment below.
-EOF-
边栏推荐
- Global and Chinese market of electric cheese grinder 2022-2028: Research Report on technology, participants, trends, market size and share
- Network security - summary and thinking of easy-to-use fuzzy tester
- 高中数学必修一
- OpenCV关于x,y坐标容易混淆的心得
- The best blog to explain the basics of compilation (share)
- High school mathematics compulsory one
- Global and Chinese markets for Salmonella typhi nucleic acid detection kits 2022-2028: Research Report on technology, participants, trends, market size and share
- Opencv common method source link (continuous update)
- 2022 Heilongjiang latest construction eight members (materialman) simulated examination questions and answers
- 16: 00 interview, came out at 16:08, the question is really too
猜你喜欢

ICMP Protocol

Carsim-路面3D形状文件参数介绍

ARP及ARP欺骗

Simple implementation scheme of transcoding and streaming (I)

Introduction to parameters of CarSim pavement 3D shape file

Web安全--核心防御机制

Matlab mathematical modeling tool

Web security -- Logical ultra vires

CarSim problem failed to start solver: path_ ID_ OBJ(X) was set to Y; no corresponding value of XXXXX?

How to build the alliance chain? How much is the development of the alliance chain
随机推荐
Jupyter Notebook常用快捷键(在命令模式中按H也可查看)
Force deduction method summary: double pointer
Constant pointer and pointer constant
高中数学必修一
Matlab-其它
樂理基礎(簡述)
ARP and ARP Spoofing
What are the platforms for selling green label domain names? What is the green label domain name like?
sqli-labs第12关
Pointer initialization
类和对象(类和类的实例化,this,static关键字,封装)
路由基础—动态路由
Longest isometric subsequence
Don't know mock test yet? An article to familiarize you with mock
Carsim-实时仿真的动画同步问题
Global and Chinese market of wire loop, 2022-2028: Research Report on technology, participants, trends, market size and share
Use Matplotlib to draw a preliminary chart
CarSim learning experience - rough translation 1
VS Code配置问题
TCP/IP—传输层