C#的五大設計原則-solid原則

什么是C#的五大設計原則,我們用人話來解釋一下,希望小伙伴們能學會:

好的,讓我們以一種幽默的方式來解釋C#的五大設計原則(SOLID):

單一職責原則(Single Responsibility Principle, SRP):別讓一個類做得像瑞士軍刀一樣樣樣都干,它會累趴下的。讓每個類專注于一件事,成就一個小專家!

開閉原則(Open/Closed Principle, OCP):代碼就像房子一樣,應該允許你隨時裝修,但不要讓你每次都得拆墻。你的類應該開放給擴展,關閉給修改。裝修可以,但別動地基。

里氏替換原則(Liskov Substitution Principle, LSP):如果它看起來像鴨子,游起來像鴨子,叫起來也像鴨子,那它就應該是個鴨子。子類應該能完全替代父類,就像鴨子替代鴨子一樣。

接口隔離原則(Interface Segregation Principle, ISP):不要逼用戶點一堆不想要的菜,分開菜單讓他們點自己喜歡的。讓接口精簡,用戶用起來才不會吐槽你。

依賴倒置原則(Dependency Inversion Principle, DIP):別總想著親自動手干活,雇個專業的幫你干!高層模塊不應該依賴低層模塊,而應該依賴于抽象。讓專業的人做專業的事,你只需要指揮就好。

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

1. 單一職責原則(SRP - Single Responsibility Principle)

不使用SRP:

public class UserService
{public void RegisterUser(string name, string email){// 保存用戶到數據庫SaveUserToDatabase(name, email);// 發送歡迎郵件SendWelcomeEmail(email);}private void SaveUserToDatabase(string name, string email){// 代碼邏輯}private void SendWelcomeEmail(string email){// 代碼邏輯}
}

在這個示例中,UserService類同時處理用戶注冊和發送郵件,職責不單一,導致類的復雜性增加,不利于維護和擴展。

使用SRP:

public class User
{public string Name { get; set; }public string Email { get; set; }
}public class UserRepository
{public void AddUser(User user) { /* 代碼 */ }public User GetUserByEmail(string email) { /* 代碼 */ }
}public class EmailService
{public void SendEmail(User user) { /* 代碼 */ }
}public class UserService
{private readonly UserRepository _userRepository;private readonly EmailService _emailService;public UserService(UserRepository userRepository, EmailService emailService){_userRepository = userRepository;_emailService = emailService;}public void RegisterUser(User user){_userRepository.AddUser(user);_emailService.SendEmail(user);}
}

在這個示例中,職責被分離到了不同的類中,UserService只負責協調這些操作,使代碼更清晰、可維護。

2. 開閉原則(OCP - Open/Closed Principle)

不使用OCP:

public class Shape
{public double Radius { get; set; }public double Width { get; set; }public double Height { get; set; }public double GetArea(string shapeType){if (shapeType == "Circle"){return Math.PI * Radius * Radius;}else if (shapeType == "Rectangle"){return Width * Height;}else{return 0;}}
}

在這個示例中,添加新的形狀類型需要修改GetArea方法的代碼,違反了開閉原則。

使用OCP:

public abstract class Shape
{public abstract double Area();
}public class Circle : Shape
{public double Radius { get; set; }public override double Area() => Math.PI * Radius * Radius;
}public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override double Area() => Width * Height;
}

在這個示例中,通過擴展Shape類,我們可以添加新的形狀而不需要修改現有的代碼,符合開閉原則。

3. 里氏替換原則(LSP - Liskov Substitution Principle)

不使用LSP:

public class Rectangle
{public virtual double Width { get; set; }public virtual double Height { get; set; }public double Area() => Width * Height;
}public class Square : Rectangle
{public override double Width{set { base.Width = base.Height = value; }}public override double Height{set { base.Width = base.Height = value; }}
}

在這個示例中,Square類違反了里氏替換原則,因為WidthHeight的行為在子類中改變了。

使用LSP:

public abstract class Shape
{public abstract double Area();
}public class Rectangle : Shape
{public double Width { get; set; }public double Height { get; set; }public override double Area() => Width * Height;
}public class Square : Shape
{public double SideLength { get; set; }public override double Area() => SideLength * SideLength;
}

在這個示例中,RectangleSquare都正確實現了ShapeArea方法,符合里氏替換原則。

4. 接口隔離原則(ISP - Interface Segregation Principle)

不使用ISP:

public interface IWorker
{void Work();void Eat();
}public class Worker : IWorker
{public void Work() { /* 代碼邏輯 */ }public void Eat() { /* 代碼邏輯 */ }
}public class Robot : IWorker
{public void Work() { /* 代碼邏輯 */ }public void Eat(){throw new NotImplementedException();}
}

在這個示例中,Robot類必須實現它不需要的Eat方法,導致接口不符合實際需求。

使用ISP:

public interface IWorkable
{void Work();
}public interface IEatable
{void Eat();
}public class Worker : IWorkable, IEatable
{public void Work() { /* 代碼邏輯 */ }public void Eat() { /* 代碼邏輯 */ }
}public class Robot : IWorkable
{public void Work() { /* 代碼邏輯 */ }
}

在這個示例中,IWorkableIEatable接口被分離,Robot類只實現了需要的接口,符合接口隔離原則。

5. 依賴倒置原則(DIP - Dependency Inversion Principle)

不使用DIP:

public class DatabaseLogger
{public void Log(string message){// 記錄日志到數據庫}
}public class UserService
{private readonly DatabaseLogger _logger = new DatabaseLogger();public void RegisterUser(string name, string email){// 記錄日志_logger.Log("Registering user " + name);// 其他代碼}
}

在這個示例中,UserService類直接依賴于具體的DatabaseLogger實現,違反了依賴倒置原則。

使用DIP:

public interface ILogger
{void Log(string message);
}public class DatabaseLogger : ILogger
{public void Log(string message){// 記錄日志到數據庫}
}public class FileLogger : ILogger
{public void Log(string message){// 記錄日志到文件}
}public class UserService
{private readonly ILogger _logger;public UserService(ILogger logger){_logger = logger;}public void RegisterUser(string name, string email){// 記錄日志_logger.Log("Registering user " + name);// 其他代碼}
}

在這個示例中,UserService類依賴于ILogger接口,而不是具體的實現,符合依賴倒置原則,使得代碼更加靈活和可擴展。

總結對比

  • 單一職責原則(SRP): 通過分離職責減少類的復雜度,使代碼更易讀和維護。不使用SRP會導致類變得龐大,職責不清,維護困難。
  • 開閉原則(OCP): 通過擴展來增加新功能,而不是修改已有代碼,提高了代碼的穩定性和可擴展性。不使用OCP會導致每次增加新功能都需要修改已有代碼,增加了出錯的風險。
  • 里氏替換原則(LSP): 確保子類可以替代基類而不會導致程序出錯,保證繼承的正確性。不使用LSP會導致子類行為不一致,破壞程序的穩定性。
  • 接口隔離原則(ISP): 通過細化接口,使得類只依賴于需要的接口,減少不必要的依賴關系。不使用ISP會導致類實現不需要的接口方法,增加了代碼的復雜度。
  • 依賴倒置原則(DIP): 通過依賴于抽象(接口或抽象類)而不是具體實現,降低模塊之間的耦合,提高代碼的靈活性和可測試性。不使用DIP會導致類之間的高耦合,難以進行單元測試和模塊替換。

通過遵循SOLID原則,可以顯著提高代碼的可維護性、可擴展性和靈活性,使開發和維護變得更加高效。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38328.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38328.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38328.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PCL 漸進形態過濾器實現地面分割

點云地面分割 一、代碼實現二、結果示例?? 概述 漸進形態過濾器:采用先腐蝕后膨脹的運算過程,可以有效濾除場景中的建筑物、植被、車輛、行人以及交通附屬設施,保留道路路面及路緣石點云。 一、代碼實現 #include <iostream> #include <pcl/io/pcd_io.h> #in…

【LeetCode】976. 三角形的最大周長

1. 題目 2. 分析 需要分析好再動手編程。 如果要構成三角形的最大周長&#xff0c;那么就需要盡可能用最長的邊構建。所以可以先對數組排個序&#xff0c;然后基于排序得到的結果從大往小的逐個檢查長度為3的窗口&#xff0c;判斷該窗口的值是否滿足三角形的構成條件&#x…

鴻蒙開發Ability Kit(程序訪問控制):【安全控件概述】

安全控件概述 安全控件是系統提供的一組系統實現的ArkUI組件&#xff0c;應用集成這類組件就可以實現在用戶點擊后自動授權&#xff0c;而無需彈窗授權。它們可以作為一種“特殊的按鈕”融入應用頁面&#xff0c;實現用戶點擊即許可的設計思路。 相較于動態申請權限的方式&am…

構造,析構,拷貝【類和對象(中)】

P. S.&#xff1a;以下代碼均在VS2019環境下測試&#xff0c;不代表所有編譯器均可通過。 P. S.&#xff1a;測試代碼均未展示頭文件stdio.h的聲明&#xff0c;使用時請自行添加。 博主主頁&#xff1a;LiUEEEEE ??????????????????? ?? …

Excel_VBA編程

在Excel中&#xff0c;VBA&#xff08;Visual Basic for Applications&#xff09;是一種強大的工具&#xff0c;可以用來自動化各種任務。下面介紹一些常用的VBA函數和程序結構&#xff1a; 常用函數 MsgBox&#xff1a;用于顯示消息框。 MsgBox "Hello, World!"In…

【python全棧系列】day07-python數據類型-集合

Python中的集合&#xff08;Set&#xff09;是一個無序的、不包含重復元素的數據結構。它主要用于數學上的集合操作&#xff0c;如并集、交集、差集和對稱差集等。集合的基本用途包括去重和關系測試。 1、集合的特性 無序性&#xff1a;集合中的元素是無序的&#xff0c;這意…

gin-vue -admin 初始化安裝后 進入 后臺首頁報錯

報錯原因&#xff1a; 因為 我是使用的phpstudy 小皮的數據庫 默認的是MySam 的引擎 mysql 引擎需要是 innoDB 解決辦法 &#xff1a; 在linux 的環境下 配置一個數據庫 &#xff0c; 我是用的是vmware 虛擬機

深入理解分布式搜索引擎 ElasticSearch,并能基于 ELK+Kafka 搭建分布式?志收集系統

Elasticsearch是一個基于Lucene的分布式、多租戶能力的全文搜索引擎。它提供了RESTful web接口和分布式多用戶能力的全文搜索引擎&#xff0c;基于Apache許可證發行。以下是對Elasticsearch的深入理解以及如何基于ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;加…

npm緩存深度解析:理解、使用與清除指南

&#x1f31f; npm緩存深度解析&#xff1a;理解、使用與清除指南 npm&#xff08;Node Package Manager&#xff09;是JavaScript編程語言的包管理器&#xff0c;廣泛用于Node.js應用程序。它不僅幫助我們安裝和管理項目依賴&#xff0c;還擁有一個強大的緩存機制來加速這一過…

[論文筆記] BlendedDataset blend goes out of bounds for list 34 for valid split

報錯&#xff1a; Traceback (most recent call last):File "/mnt/cpfs/kexin/dlc_code/qwen2/Pai-Megatron-Patch/examples/qwen2/pretrain_qwen.py", line 211, in <module> (<megatron.core.datasets.gpt_dataset.GPTDataset object at 0x7f491886bf10&…

《昇思25天學習打卡營第8天|CarpeDiem》

《昇思25天學習打卡營第8天|CarpeDiem》 模型訓練構建數據集定義神經網絡模型定義超參、損失函數和優化器超參損失函數優化器 訓練與評估 打卡 今天是昇思25天學習打卡營的第8天&#xff0c;終于迎來 模型訓練 的部分了&#xff01;&#xff01;&#xff01; 興奮 發癲 模型訓…

SSH遠程命令執行漏洞(CVE-2024-6387)驗證

0x01、漏洞名稱 OpenSSH遠程代碼執行漏洞 &#xff08;CVE-2024-6387&#xff09; 0x02、漏洞簡介 ? OpenSSH是SSH&#xff08;Secure SHell&#xff09;協議的開源實現&#xff0c;它通過不安全的網絡在兩個不受信任的主機之間提供安全的加密通信。OpenSSH 廣泛用于基于Un…

數據庫。

數據庫安全性 論述題5’ 編程題10’ sql語言實現權限控制 一、概述 1、不安全因素 &#xff08;1&#xff09;?授權對數據庫的惡意存取和破壞 &#xff08;2&#xff09;數據庫中重要的數據泄露 &#xff08;3&#xff09;安全環境的脆弱性 2、?主存取控制?法 gr…

【ajax實戰06】進行文章發布

本文章目標&#xff1a;收集文章內容&#xff0c;并提交服務器保存 一&#xff1a;基于form-serialize插件收集表單數據 form-serialize插件僅能收集到表單數據&#xff0c;除此之外的數據無法收集到 二&#xff1a;基于axios提交到服務器保存 三&#xff1a;調用alert警告…

基于KMeans的航空公司客戶數據聚類分析

&#x1f490;大家好&#xff01;我是碼銀~&#xff0c;歡迎關注&#x1f490;&#xff1a; CSDN&#xff1a;碼銀 公眾號&#xff1a;碼銀學編程 實驗目的和要求 會用Python創建Kmeans聚類分析模型使用KMeans模型對航空公司客戶價值進行聚類分析會對聚類結果進行分析評價 實…

Linux修煉之路之進程概念,fork函數,進程狀態

目錄 一&#xff1a;進程概念 二&#xff1a;Linux中的進程概念 三&#xff1a;用getpid(),getppid()獲取該進程的PID,PPID 四&#xff1a;用fork()來創建子進程 五&#xff1a;操作系統學科的進程狀態 六&#xff1a;Linux中的進程狀態 接下來的日子會順順利利&#xf…

【區塊鏈+基礎設施】深證金融區塊鏈平臺 | FISCO BCOS應用案例

作為數據交換密集型行業&#xff0c;資本市場是區塊鏈創新應用的重要領域&#xff0c;區塊鏈技術可以有效解決諸多痛點問題。比 如&#xff0c;針對信息不對稱的問題&#xff0c;區塊鏈技術通過將整個企業的經營活動信息上鏈&#xff0c;有效降低盡調成本&#xff0c;為投融資決…

配置windows環境下獨立瀏覽器爬蟲方案【不依賴系統環境與chrome】

引言 由于部署瀏覽器爬蟲的機器瀏覽器版本不同&#xff0c;同時也不想因為部署了爬蟲導致影響系統瀏覽器數據&#xff0c;以及避免爬蟲過程中遇到的chrome與webdriver版本沖突。我決定將特定版本的chrome瀏覽器與webdriver下載到項目目錄內&#xff0c;同時chrome_driver在初始…

我使用 GPT-4o 幫我挑西瓜

在 5 月 15 日&#xff0c;OpenAI 旗下的大模型 GPT-4o 已經發布&#xff0c;那時網絡上已經傳開&#xff0c; 但很多小伙伴始終沒有看到 GPT-4o 的體驗選項。 在周五的時候&#xff0c;我組建的 ChatGPT 交流群的伙伴已經發現了 GPT-4o 這個選項了&#xff0c;是在沒有充值升…

NSSCTF-Web題目21(文件上傳-phar協議、RCE-空格繞過)

目錄 [NISACTF 2022]bingdundun~ 1、題目 2、知識點 3、思路 [FSCTF 2023]細狗2.0 4、題目 5、知識點 6、思路 [NISACTF 2022]bingdundun~ 1、題目 2、知識點 文件上傳&#xff0c;phar偽協議 3、思路 點擊upload&#xff0c;看看 這里提示我們可以上傳圖片或壓縮包&…