[](https://hackmd.io/8BvrDK1rSLG3QDlNVAbeXw) ###### tags: `2023鐵人賽` `qiita` `SOLID` # [2023 15th鐵人賽] Day10 - 透過圖文理解 S.O.L.I.D 原則  > 原文連結:[The S.O.L.I.D Principles in Pictures](https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898) > 本文所刊登的圖片,皆屬原作者 Ugonna Thelma 所有。 這篇比較特別一點,是從「[イラストで理解するSOLID原則 - Qiita](https://qiita.com/baby-degu/items/d058a62f145235a0f007)」這篇翻譯得知英文原文,因此會以英翻中為主。 本文將以圖解方式,依序說明 SOLID 原則: + Single Responsibility 單一職責原則 + Open-Closed 開放封閉原則 + Liskov Substitution 里氏替換原則 + Interface Segregation 介面分離原則 + Dependency Inversion 依賴反向原則 以下正文開始。 --- [toc] ## 前言 若您熟悉[物件導向程式設計](https://en.wikipedia.org/wiki/Object-oriented_programming),那麼您應該聽過 [**SOLID**](https://en.wikipedia.org/wiki/SOLID) 原則。 這五個軟體開發原則,是在建立軟體時應遵循的指南,使軟體更容易擴展和維護。這些原則是由軟體工程師 [Robert C. Martin](https://en.wikipedia.org/wiki/Robert_C._Martin) 所推廣。 網路上雖然有許多關於 **SOLID** 的優秀文章,但我很少看到有附圖片的範例。這對於像我這樣的視覺學習者來說,想要參與學習是有點困難的。 因此,本文的主要目的就是通過插圖來幫助理解這些原則,並強調每個原則的目標。 其中一些原則可能看起來很類似,但其實並不針對**相同的目標**。即使看起來相似,也可能滿足一個原則並違反另一個原則。 為了使本篇內容簡單易懂,將使用詞語「**Class(類別)**」,但請注意這個詞語在本文也適用於 **Function(函數)、Method(方法)或** **Module(模組)**。 > **更新*** > > 有留言在本文中提到,「開放封閉原則 OCP」可能違反了「單一職責原則 SRP」,但需注意本文目的是單獨解釋每一個原則。 > > 此外,責任(或角色)並不同於行動。在「單一職責原則」中,使用 "I am Painter",而在「開放封閉原則」中,則使用 "I can Paint"。 > > 這一點非常重要,為了履行一個責任(或角色)可以執行多個動作。Class 應該具備一個責任(SRP),但實現該責任的功能應該能夠擴展的(OCP)。 > 現在,讓我們開始吧! ## SOLID 原則 ### S(Single Responsibility)單一職責原則 > 類別應該具備單一職責。 >  如果一個類別有多個職責,將提高錯誤的可能性。因為修改其中一個職責,可能會連帶影響其他職責。 #### 目標 這個原則的目標是確保操作分離,即使變更可能導致錯誤發生,也不會對其他無關的操作產生影響。 ### O(Open-Closed)開放封閉原則 > 類別應該對擴展開放,但對修改封閉。 >  修改一個類別的當前行為,將會對使用該類別的所有系統造成影響。 若希望類別執行更多功能,理想的方法是添加功能到既有的函數,而**不是**進行修改。 #### 目標 這個原則的目標是擴展類別功能,而不改變該類別現有行為。藉此避免在使用該類別的地方出現錯誤。 ### L(Liskov Substitution)里氏替換原則 > 若 S 是 T 的子類別(subtype),則程式中 T 型的 Object 可被 S 型的 Object 替換,且不改變程式的任何屬性。  當一個**子**類別無法與其**父**類別執行相同的操作時,這可能會引發錯誤。 若由一個類別建立另一個類別,該類別會成為**父**,新的類別成為**子**。**子**類別必須能夠執行**父**類別能夠執行的所有操作。這個過程稱作**繼承**。 **子**類別在處理與**父**類別相同的請求時,將會產生相同的結果,或相同類型的結果。 圖片顯示**父**類別可提供咖啡(任何種類的咖啡),而**子**類別提供卡布奇諾是可接受的,因爲卡布奇諾屬於咖啡的一種,但提供水則是不可接受的。 當**子**類別不符合這些要求時,代表著**子**類別完全改變,如此即違反了這個原則。 #### 目標 這個原則的目標是強制一致性,確保父類別或其子類別能夠以相同的方式使用,而不會出現任何錯誤。 ### I(Interface Segregation)介面分離原則 > 客戶端不應被強迫依賴於未使用的方法。  在類別中執行不必要的操作將造成許多浪費,若該類別無法執行這些操作,則可能導致意外的錯誤。 類別應該只執行履行其職責所需的操作。其他操作應該完全刪除,或如果將來可能被其他類別使用,則應該移至其他地方。 #### 目標 這個原則的目標是將操作的集合分割成更小,以確保類別僅執行所需的功能。 ### D(Dependency Inversion)依賴反向原則 > 高層模組不應該依賴於低層模組。兩者都應依賴於抽象化。 抽象化不應該依賴於細節。細節應該依賴於抽象化。  首先,簡單定義這裡使用到的術語。 **高層模組(或類別)**:使用工具執行動作的類別 **低層模組(或類別)**:執行動作所需的工具 **抽象**:表示連接兩個類別的介面 **細節**:工具的操作方式 在這個原則中,類別不應該與執行動作的工具混合在一起。相反地,工具應該與可以連接類別的介面融為一體。 此外,類別和介面都不應該知道工具的操作方式,但工具必須符合介面的規範。 #### 目標 這個原則的目標是透過引入一個介面,以減少高層類別對低層類別的依賴。 ## 結語 本篇針對這五個原則進行說明,並強調其目標。這些原則的目標是降低發生問題的可能,使程式碼易於調整、擴展及測試。 非常感謝您的閱讀。希望您對這個主題有更深的瞭解,並且在閱讀本文的過程能像我寫作的過程一樣愉快。 若有任何問題或建議,歡迎留下評論。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up