当前位置:网站首页>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-
边栏推荐
- Use the kaggle training model and download your own training model
- Li Kou daily one question brushing summary: binary tree chapter (continuous update)
- The best blog to explain the basics of compilation (share)
- Comparable,Comparator,Clonable 接口使用剖析
- Opencv3 6.3 reduced pixel sampling with filters
- Chinese garbled code under vscade
- Use C language to receive JSON strings
- sqli-labs第8关(布尔盲注)
- IP协议与IP地址
- DWORD ptr[]
猜你喜欢

Gateway 简单使用

ICMP Protocol

Analysis of the use of comparable, comparator and clonable interfaces

Don't know mock test yet? An article to familiarize you with mock

ARP及ARP欺骗

乐理基础(简述)

樂理基礎(簡述)

ARP and ARP Spoofing

sqli-labs第8关(布尔盲注)

C language custom types - structure, bit segment (anonymous structure, self reference of structure, memory alignment of structure)
随机推荐
Mutex
Global and Chinese markets for conventional rubber track 2022-2028: Research Report on technology, participants, trends, market size and share
The best blog to explain the basics of compilation (share)
HCIA—数据链路层
程序猿学英语-指令式编程
Carla-UE4Editor导入RoadRunner地图文件(保姆级教程)
Live broadcast platform development, flexible menu, and freely adjust the horizontal size of the menu bar
Global and Chinese markets for magnetic resonance imaging (MRI) transmission 2022-2028: Research Report on technology, participants, trends, market size and share
2022 Heilongjiang latest construction eight members (materialman) simulated examination questions and answers
Force deduction method summary: double pointer
When a custom exception encounters reflection
Use of OpenCV 6.4 median filter
使用Matplotlib绘制图表初步
c语言自定义类型——结构体,位段(匿名结构体,结构体的自引用,结构体的内存对齐)
HCIA—应用层
Force deduction method summary: find classes
Matlab-其它
Multi site high availability deployment
Opencv's experience of confusing X and Y coordinates
Sqlyog remote connection to MySQL database under centos7 system