【設計模式】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.pswp.cn/pingmian/73029.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73029.shtml
英文地址,請注明出處:http://en.pswp.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…