news 2026/4/16 17:15:40

SOLID软件设计原则 解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SOLID软件设计原则 解析

前言:在平时coding过程中,大部分程序员可能把更多精力和时间花在功能的实现和完成上面,对于代码的可读性、可读性及可扩展性没有过多的关注,这可能会造成后期功能扩展困难、新人无法理解等问题。这里介绍一些软件代码设计原则,帮助大家提升代码质量。

目录

一、SOLID软件设计原则

二、单一职责原则(Single Responsible Principle)

二、开闭原则(Open Close Principle)

三、里氏替换原则(Liskov Substitution Principle)

四、接口隔离原则(Interface Segregation Principle)

五、依赖倒置原则(Dependency Inversion Principle)


一、SOLID软件设计原则

SOLID是面向对象软件设计中5个基础设计原则的简写,由Robert C. Martin提出,是设计模式的指导思想。这些原则包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则、依赖倒置原则。下面章节分别展开介绍。

二、单一职责原则(Single Responsible Principle)

1)定义:一个类应当只做一件事情,只有一个引起它变化的原因

2)思想:避免一个类同时负责多个功能,否则对一个功能的修改可能会影响到其他功能,修改扩展成本增加。

3)示例

反例:一个UserManager类同时负责用户信息管理用户日志记录,如果日志的存储方式修改(比如从本地文件改成数据库),就需要修改这个类,违反了单一职责。

正例:拆分为两个类:

// 只负责用户信息的管理 class UserManager { public: void addUser(const std::string& username) { // 处理用户添加的逻辑 } void deleteUser(const std::string& username) { // 处理用户删除的逻辑 } }; // 只负责用户相关的日志记录 class UserLogger { public: void logUserOperation(const std::string& username, const std::string& operation) { // 处理日志记录的逻辑 } };

二、开闭原则(Open Close Principle)

1)定义:软件模块(类、函数等)应该对扩展开放,对修改关闭。

2)思想:当需要新增功能时,应当通过扩展已有代码模块来实现,而不是在已有代码上直接修改、打补丁,防止补丁上打补丁,时间长了就难以维护了。

3)示例

反例:一个ShapeCalculator类,计算不同图形的面积,如果新增一种图形(比如椭圆),就需要修改类的代码:

// 反例:新增图形需要修改这个类 class ShapeCalculator { public: double calculateArea(const std::string& shapeType, double param1, double param2) { if (shapeType == "circle") { return M_PI * param1 * param1; } else if (shapeType == "rectangle") { return param1 * param2; } // 新增椭圆需要在这里加else if return 0; } };

正例:通过抽象类+继承实现

// 抽象的图形类 class Shape { public: virtual double calculateArea() const = 0; virtual ~Shape() = default; }; // 圆形类,继承Shape class Circle : public Shape { private: double radius; public: Circle(double r) : radius(r) {} double calculateArea() const override { return M_PI * radius * radius; } }; // 矩形类,继承Shape class Rectangle : public Shape { private: double width; double height; }; // 面积计算器,只依赖抽象类,新增图形不需要修改这个类 class ShapeCalculator { public: double calculateArea(const Shape& shape) { return shape.calculateArea(); } };

上述代码中出现了虚函数和抽象类的概念,如需要可参考之前的文章:C++ 虚函数 解析指南-CSDN博客

三、里氏替换原则(Liskov Substitution Principle)

1)定义:子类对象可以替换父类对象在程序中的所有使用场景,且不会改变程序的正确性。

2)思想:子类必须完全实现父类功能,不能破坏父类的行为,避免继承关系的滥用。

3)示例

反例:正方形继承矩形,但是正方形的宽和高必须相等,修改宽的时候高也会变化,破坏了矩形的行为

class Rectangle { protected: double width; double height; public: void setWidth(double w) { width = w; } void setHeight(double h) { height = h; } double getArea() { return width * height; } }; // 反例:正方形继承矩形,但是setWidth和setHeight的行为不符合父类的约定 class Square : public Rectangle { public: void setWidth(double w) override { width = w; height = w; } void setHeight(double h) override { width = h; height = h; } };

正例:重新设计继承关系,使得正方形与矩形都继承抽象的Shape类。

四、接口隔离原则(Interface Segregation Principle)

1)定义:客户端不应当依赖它不需要的接口,一个类对另一个类的依赖应当建立在最小接口上。

2)思想:避免设计大而全的接口,接口应当拆分多个小的,高内聚、低耦合。

3)示例

反例:一个大的Worker接口,包含了所有工作相关的方法,但是不同的 worker 只需要其中一部分

// 反例:大而全的接口 class Worker { public: virtual void work() = 0; virtual void eat() = 0; virtual void sleep() = 0; }; // 机器人只需要work,但是必须实现eat和sleep class Robot : public Worker { public: void work() override { /* 工作逻辑 */ } void eat() override { /* 机器人不需要吃饭,空实现 */ } void sleep() override { /* 机器人不需要睡觉,空实现 */ } };

正例:拆分为小接口

// 只包含工作的接口 class Workable { public: virtual void work() = 0; virtual ~Workable() = default; }; // 只包含休息相关的接口 class Restable { public: virtual void eat() = 0; virtual void sleep() = 0; virtual ~Restable() = default; }; // 机器人只实现Workable接口 class Robot : public Workable { public: void work() override { /* 工作逻辑 */ } }; // 人类实现Workable和Restable接口 class HumanWorker : public Workable, public Restable { public: void work() override { /* 工作逻辑 */ } void eat() override { /* 吃饭逻辑 */ } void sleep() override { /* 睡觉逻辑 */ } };

五、依赖倒置原则(Dependency Inversion Principle)

1)定义:上层模块不应当依赖底层模块抽象不应当依赖细节,细节应当依赖抽象。

2)思想:通过抽象(抽象类或接口)实现上层与底层解耦,使得模块之间依赖关系倒置,提高灵活性。

3)示例

反例:上层模块ReportGenerator直接依赖底层模块MySQLDatabase,如果需要切换数据库(比如改成PostgreSQL),就需要修改ReportGenerator

// 反例:上层依赖底层的具体实现 class MySQLDatabase { public: std::string getData() { return "从MySQL获取的数据"; } }; class ReportGenerator { private: MySQLDatabase db; public: std::string generateReport() { return "报告内容:" + db.getData(); } };

正例:通过抽象接口解耦

// 抽象的数据库接口 class Database { public: virtual std::string getData() const = 0; virtual ~Database() = default; }; // MySQL的具体实现,依赖抽象接口 class MySQLDatabase : public Database { public: std::string getData() const override { return "从MySQL获取的数据"; } }; // PostgreSQL的具体实现,依赖抽象接口 class PostgreSQLDatabase : public Database { public: std::string getData() const override { return "从PostgreSQL获取的数据"; } }; // 高层模块依赖抽象接口,而不是具体实现 class ReportGenerator { private: const Database& db; public: // 通过构造函数注入依赖 ReportGenerator(const Database& database) : db(database) {} std::string generateReport() { return "报告内容:" + db.getData(); } };

结束语:一般这5种原则不会孤立存在,通常两三个会结合在一起使用。读者可参考进行理解消化,最终目的是应用于实际项目中,实现代码质量显著提升。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 8:31:14

如何快速部署电子取证工具:ForensicsTool完整安装配置指南

如何快速部署电子取证工具:ForensicsTool完整安装配置指南 【免费下载链接】ForensicsTool 简单的取证工具 项目地址: https://gitcode.com/gh_mirrors/fo/ForensicsTool 想要学习电子取证技术却不知从何入手?ForensicsTool 这款开源电子数据取证…

作者头像 李华
网站建设 2026/4/16 11:07:14

PRQL多语言集成:企业级数据查询的革命性解决方案

PRQL多语言集成:企业级数据查询的革命性解决方案 【免费下载链接】prql PRQL/prql: 是一个类似于 SQL 的查询语言实现的库。适合用于查询各种数据库和数据格式。特点是支持多种数据库类型,提供了类似于 SQL 的查询语言。 项目地址: https://gitcode.co…

作者头像 李华
网站建设 2026/4/16 12:39:51

Qwen3-Omni多模态AI模型终极部署指南:5分钟快速上手实战

想要在本地快速体验多模态AI的强大功能吗?Qwen3-Omni-30B-A3B-Instruct作为开源AI领域的明星产品,原生支持文本、图像、音视频输入,还能实时生成语音响应。本文将带你从零开始,5分钟完成环境配置,快速掌握这个智能对话…

作者头像 李华
网站建设 2026/4/16 11:06:12

Node.js ESC/POS打印实战手册:解锁硬件控制新境界

Node.js ESC/POS打印实战手册:解锁硬件控制新境界 【免费下载链接】node-escpos 🖨️ ESC/POS Printer driver for Node.js 项目地址: https://gitcode.com/gh_mirrors/no/node-escpos 在数字化转型浪潮中,打印机作为连接数字世界与物…

作者头像 李华
网站建设 2026/4/12 10:59:12

国巨薄膜精密电阻RT0805系列的噪声水平及适合的应用

国巨(YAGEO)RT0805系列薄膜精密电阻,是目前市场上兼具高精度、高稳定性与小型化优势的0805封装电阻代表。其具体系列包括RT0805FRB07、RT0805FRD07、RT0805FRE07、RT0805FRE10、RT0805FRE13、RT0805FRF07、RT0805LRB07、RT0805LRC07、RT0805L…

作者头像 李华