【设计模式】SOLID 设计原则概述

SOLID 是面向对象设计中的五大原则,不管什么面向对象的语言, 这个准则都很重要,如果你没听说过,赶紧先学一下。它可以提高代码的可维护性可扩展性可读性,使代码更加健壮、易于测试和扩展。SOLID 代表以下五个设计原则:

  1. S - 单一职责原则(Single Responsibility Principle, SRP)
  2. O - 开闭原则(Open/Closed Principle, OCP)
  3. L - 里氏替换原则(Liskov Substitution Principle, LSP)
  4. I - 接口隔离原则(Interface Segregation Principle, ISP)
  5. D - 依赖倒置原则(Dependency Inversion Principle, DIP)

1. 单一职责原则(SRP)

一个类应该仅有一个引起它变化的原因
一个类应该仅负责一个功能,否则后期修改代码时,可能会影响其他无关功能。

❌ 违反 SRP 的例子

class Report {
public:void generateReport() { /* 生成报表 */ }void printReport() { /* 打印报表 */ }void saveToFile() { /* 保存到文件 */ }
};

问题:
Report 负责 生成报表打印报表保存报表,违反了 SRP。

✅ 遵循 SRP 的改进

class Report {
public:void generateReport() { /* 生成报表 */ }
};class ReportPrinter {
public:void printReport(Report& report) { /* 打印报表 */ }
};class ReportSaver {
public:void saveToFile(Report& report) { /* 保存到文件 */ }
};

改进点:

  • Report 只负责生成报表
  • ReportPrinter 负责打印
  • ReportSaver 负责存储

这样每个类的变更都不会影响其他功能,符合 SRP。


2. 开闭原则(OCP)

软件实体(类、模块、函数)应该对扩展开放,对修改关闭。
即:新增功能时,应该通过扩展代码,而不是修改已有代码

❌ 违反 OCP 的例子

class PaymentProcessor {
public:void processPayment(std::string paymentType) {if (paymentType == "CreditCard") {// 处理信用卡支付} else if (paymentType == "PayPal") {// 处理 PayPal 支付}}
};

问题:

  • 如果新增 Apple Pay,需要修改 processPayment(),违反 OCP。
  • 代码越复杂,修改的风险越高。

✅ 遵循 OCP 的改进

class Payment {
public:virtual void pay() = 0;virtual ~Payment() = default;
};class CreditCardPayment : public Payment {
public:void pay() override { /* 处理信用卡支付 */ }
};class PayPalPayment : public Payment {
public:void pay() override { /* 处理 PayPal 支付 */ }
};class PaymentProcessor {
public:void processPayment(Payment& payment) {payment.pay();}
};

改进点:

  • 新增支付方式时,不需要修改 PaymentProcessor,只需新增一个类(符合 OCP)。
  • 通过 多态 使代码更加灵活。

3. 里氏替换原则(LSP)

子类必须能够替换基类,并且不会破坏程序的正确性

❌ 违反 LSP 的例子

class Bird {
public:virtual void fly() { /* 飞行逻辑 */ }
};class Penguin : public Bird {
public:void fly() override {throw std::runtime_error("企鹅不会飞!");}
};

问题:

  • Penguin 继承了 Bird,但企鹅不会飞!
  • Penguin::fly() 违背了父类的逻辑,可能导致程序崩溃。

✅ 遵循 LSP 的改进

class Bird {
public:virtual void move() = 0;
};class FlyingBird : public Bird {
public:void move() override { /* 飞行逻辑 */ }
};class Penguin : public Bird {
public:void move() override { /* 企鹅走路 */ }
};

改进点:

  • 抽象出 FlyingBirdPenguin,使 Penguin 不继承 fly(),从而避免违反 LSP。

4. 接口隔离原则(ISP)

不应该强迫类实现它们不需要的接口
即:一个接口不应该承担过多职责,而应该拆分成多个专门的接口

❌ 违反 ISP 的例子

class Worker {
public:virtual void work() = 0;virtual void eat() = 0;
};
class Robot : public Worker {
public:void work() override { /* 机器人工作 */ }void eat() override { throw std::runtime_error("机器人不吃饭!"); }
};

问题:

  • Robot 不需要 eat(),但仍然要实现它,违反 ISP

✅ 遵循 ISP 的改进

class Workable {
public:virtual void work() = 0;
};class Eatable {
public:virtual void eat() = 0;
};class Human : public Workable, public Eatable {
public:void work() override { /* 人工作 */ }void eat() override { /* 人吃饭 */ }
};class Robot : public Workable {
public:void work() override { /* 机器人工作 */ }
};

改进点:

  • Worker 拆分成 WorkableEatable,避免不必要的实现。

5. 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,而应该依赖于抽象(接口)

❌ 违反 DIP 的例子

class LEDLight {
public:void turnOn() { /* 打开 LED 灯 */ }
};class Switch {
private:LEDLight light;
public:void operate() { light.turnOn(); }
};

问题:

  • Switch 直接依赖 LEDLight,如果要支持 白炽灯,必须修改 Switch,违反 OCP 和 DIP

✅ 遵循 DIP 的改进

class Light {
public:virtual void turnOn() = 0;virtual ~Light() = default;
};class LEDLight : public Light {
public:void turnOn() override { /* 打开 LED 灯 */ }
};class IncandescentLight : public Light {
public:void turnOn() override { /* 打开白炽灯 */ }
};class Switch {
private:Light& light;
public:Switch(Light& l) : light(l) {}void operate() { light.turnOn(); }
};

改进点:

  • Switch 依赖 Light 接口,不依赖具体的 LEDLight,符合 DIP
  • 以后要支持新灯泡 不修改 Switch 代码。

总结

原则含义好处
SRP一个类只做一件事降低耦合,提高可维护性
OCP类应对扩展开放,对修改关闭增加功能时不修改已有代码
LSP子类可以替换父类,不影响功能确保继承不会破坏系统
ISP接口应该小而精,不要强迫实现不需要的功能降低实现负担,提高灵活性
DIP依赖接口,不依赖具体实现提高可扩展性,降低耦合

结论

遵循 SOLID 原则可以写出更好的代码,使系统更易扩展、维护和测试。在设计类和模块时,应尽量减少耦合,提高可复用性,避免不必要的修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/73029.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可发1区的超级创新思路:基于注意力机制的DSD-CNN时间序列预测模型(功率预测、交通流量预测、故障检测)

首先声明,该模型为原创!原创!原创! 一、应用场景 该模型主要用于时间序列数据预测问题,包含功率预测、电池寿命预测、电机故障检测等等 二、模型整体介绍(本文以光伏功率预测为例) DSD-CNN(Depthwise-Spacewise Separable CNN)结合通道注意力机制,通过以下创新提升…

wsl2配置xv6全解(包括22.04Jammy)

文章目录 获取xv6源代码Ubuntu20.04 Version安装指令成功测试参考MIT2021年官方文档 24.04 Version安装指令成功测试参考MIT2024年官方文档 Ubuntu 22.04没有官方文档? 配置大体流程1. 卸载原本qemu(如果之前安装了)2. clone qemu官方源代码&…

招聘面试季--一文顿悟,Java中字节流和字符流的区别及使用场景上的差异

‌一、核心区别‌ ‌特性‌‌字节流‌‌字符流‌‌数据单位‌以字节(8-bit)为单位处理数据(如0xA1)以字符(16-bit Unicode)为单位处理数据(如A, 你)‌基类‌InputStream / OutputSt…

车载以太网网络测试-16【传输层-UDP】

目录 1 摘要2 车载以太网传输层概述3 车载以太网UDP协议3.1 车载以太网UDP协议的作用3.2 UDP报文帧结构3.3 UDP协议的通信过程3.3.1 通信过程3.3.2 实例示例3.3.3 代码示例 4 总结 1 摘要 车载以太网的第五层是传输层,它在车载网络架构中扮演着至关重要的角色。主要…

深度强化学习中的深度神经网络优化策略:挑战与解决方案

I. 引言 深度强化学习(Deep Reinforcement Learning,DRL)结合了强化学习(Reinforcement Learning,RL)和深度学习(Deep Learning)的优点,使得智能体能够在复杂的环境中学…

无人机点对点技术要点分析!

一、技术架构 1. 网络拓扑 Ad-hoc网络:无人机动态组建自组织网络,节点自主协商路由,无需依赖地面基站。 混合架构:部分场景结合中心节点(如指挥站)与P2P网络,兼顾集中调度与分布式协同。 2.…

MQ,RabbitMQ,MQ的好处,RabbitMQ的原理和核心组件,工作模式

1.MQ MQ全称 Message Queue(消息队列),是在消息的传输过程中 保存消息的容器。它是应用程序和应用程序之间的通信方法 1.1 为什么使用MQ 在项目中,可将一些无需即时返回且耗时的操作提取出来,进行异步处理&#xff0…

django怎么配置404和500

在 Django 中,配置 404 和 500 错误页面需要以下步骤: 1. 创建自定义错误页面模板 首先,创建两个模板文件,分别用于 404 和 500 错误页面。假设你的模板目录是 templates/。 404 页面模板 创建文件 templates/404.html&#x…

各类神经网络学习:(四)RNN 循环神经网络(下集),pytorch 版的 RNN 代码编写

上一篇下一篇RNN(中集)待编写 代码详解 pytorch 官网主要有两个可调用的模块,分别是 nn.RNNCell 和 nn.RNN ,下面会进行详细讲解。 RNN 的同步多对多、多对一、一对多等等结构都是由这两个模块实现的,只需要将对输入…

深度学习篇---深度学习中的范数

文章目录 前言一、向量范数1.L0范数1.1定义1.2计算式1.3特点1.4应用场景1.4.1特征选择1.4.2压缩感知 2.L1范数(曼哈顿范数)2.1定义2.2计算式2.3特点2.4应用场景2.4.1L1正则化2.4.2鲁棒回归 3.L2范数(欧几里得范数)3.1定义3.2特点3…

星越L_灯光操作使用讲解

目录 1.开启前照灯 2左右转向灯、远近灯 3.auto自动灯光 4.自适应远近灯光 5.后雾灯 6.调节大灯高度 1.开启前照灯 2左右转向灯、远近灯 3.auto自动灯光 系统根据光线自动开启灯光

Stable Diffusion lora训练(一)

一、不同维度的LoRA训练步数建议 2D风格训练 数据规模:建议20-50张高质量图片(分辨率≥10241024),覆盖多角度、多表情的平面风格。步数范围:总步数控制在1000-2000步,公式为 总步数 Repeat Image Epoch …

AI 生成 PPT 网站介绍与优缺点分析

随着人工智能技术不断发展,利用 AI 自动生成 PPT 已成为提高演示文稿制作效率的热门方式。本文将介绍几款主流的 AI PPT 工具,重点列出免费使用机会较多的网站,并对各平台的优缺点进行详细分析,帮助用户根据自身需求选择合适的工具…

使用Systemd管理ES服务进程

Centos中的Systemd介绍 CentOS 中的 Systemd 详细介绍 Systemd 是 Linux 系统的初始化系统和服务管理器,自 CentOS 7 起取代了传统的 SysVinit,成为默认的初始化工具。它负责系统启动、服务管理、日志记录等核心功能,显著提升了系统的启动速…

【一维前缀和与二维前缀和(简单版dp)】

1.前缀和模板 一维前缀和模板 1.暴力解法 要求哪段区间,我就直接遍历那段区间求和。 时间复杂度O(n*q) 2.前缀和 ------ 快速求出数组中某一个连续区间的和。 1)预处理一个前缀和数组 这个前缀和数组设定为dp,dp[i]表示:表示…

在Windows和Linux系统上的Docker环境中使用的镜像是否相同

在Windows和Linux系统上的Docker环境中使用的镜像是否相同,取决于具体的运行模式和目标平台: 1. Linux容器模式(默认/常见场景) Windows系统: 当Windows上的Docker以Linux容器模式运行时(默认方式&#xf…

植物来源药用天然产物的合成生物学研究进展-文献精读121

植物来源药用天然产物的合成生物学研究进展 摘要 大多数药用天然产物在植物中含量低微,提取分离困难;而且这些化合物一般结构复杂,化学合成难度大,还容易造成环境污染。基于合成生物学技术获得药用天然产物具有绿色环保和可持续发…

JavaScript |(五)DOM简介 | 尚硅谷JavaScript基础实战

学习来源:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 笔记来源:在这位大佬的基础上添加了一些东西,欢迎大家支持原创,大佬太棒了:JavaScript |(五)DOM简介 | 尚硅谷JavaScript基础…

浏览器工作原理深度解析(阶段二):HTML 解析与 DOM 树构建

一、引言 在阶段一中,我们了解了浏览器通过 HTTP/HTTPS 协议获取页面资源的过程。本阶段将聚焦于浏览器如何解析 HTML 代码并构建 DOM 树,这是渲染引擎的核心功能之一。该过程可分为两个关键步骤:词法分析(Token 化)和…

The Illustrated Stable Diffusion

The Illustrated Stable Diffusion 1. The components of Stable Diffusion1.1. Image information creator1.2. Image Decoder 2. What is Diffusion anyway?2.1. How does Diffusion work?2.2. Painting images by removing noise 3. Speed Boost: Diffusion on compressed…