物件導向設計原則 - SOLID

更新 發佈閱讀 8 分鐘

本筆記除了以文字說明SOLID設計原則以外,並以Java code實際舉例。


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

  • 每個人負責屬於自己的職責,不該承擔太多職責,大家各自做自己應該做的事情,且不會互相干擾。

以下舉例說明,假設有個Employee類別,calculatePay()用來計算薪資,是屬於會計部的需求,genHoursReport()用來產生工時報表,是屬於人資部的需求。

calculateWorkingHours() 用來計算工時,calculatePay()與genHoursReport() 方法都依賴這個方法,也就是無論是計算薪資或是產生工時報表,都需要先計算出工時。

假設會計部門要求要更改計算薪資的方式,需要動到計算工時的邏輯calculateWorkingHours(),由於產生工時報表的方法也會呼叫這個method來計算工時,因此這個修改有可能會導致工時報表錯誤的問題,也就是為了會計部門的需求更動,會影響到人資部門的需求功能。

因此問題就浮現了,Employee class做太多事情了,把其他人的職責也囊括進來這邊,會計部門的需求改變會影響到人資部門的功能,這就不符合SRP了。

vocus|新世代的創作平台

因此,需要把不同的職責拆分到不同的類別,以免互相影響:

vocus|新世代的創作平台

如此將會計的計算薪資與人資的工時報表拆開為獨自的類別(將不同的責任方法拆分到不同的類別),內部有各自的計算工時邏輯,互不影響。會計部門的計算工時邏輯更動,不會影響人資部門的功能了。


Open/Closed Principle (OCP) 開放封閉原則

  • 「對擴充開放,對修改封閉」: 需求變動時,可以對既有的程式碼進行擴展,而不須修改原有的程式碼。

續上程式碼,修改如下:

vocus|新世代的創作平台


vocus|新世代的創作平台

要根據不同角色計算薪資,這樣的程式碼,每當有一個新的role就要去改switch的code,增加一個case與對應的method,來計算對應的薪資,如此就違反OCP原則了,要擴展不應該要去改原本的程式碼

因此為了符合OCP原則,我們修改一下code:

vocus|新世代的創作平台
vocus|新世代的創作平台
vocus|新世代的創作平台

如此修改,日後若要擴充新的Role,只需新增一個XXXRole class,並且定義calcSalary()方法,將薪資計算邏輯寫在這,就完成了。擴充功能完全不需要動到原本的code,即符合OCP原則。


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

  • 當子類別替換掉父類別時,其功能不受影響。
  • 子類別繼承父類別可以擴充新的功能,不應覆寫原本父類定義的功能,若要覆寫就必須符合原來預期的行為。

這邊修改一下剛剛的role extends的code,CEORole繼承了Role且覆寫了setName() 方法,將原本父類別setName的行為改掉了,導致發生預期之外的錯誤,這就是違反LSP原則。

從輸出的結果來看,子類的行為改變(覆寫)了父類原本的行為,造成子類無法替代父類,即違反LSP原則。

vocus|新世代的創作平台

Output:

Role Name: ABC
Role Name: CEO

Interface Segregation Principle (ISP) 介面隔離原則

  • 將龐大的介面拆分為更小且具體的介面,讓客戶只需實作他們需要的方法,不應有用不到的功能可以呼叫。

沿用上述code,修改成如下:

vocus|新世代的創作平台

假設讀取報表(readReport)是祕書才會做的事,審核假單(verifyBreakLog)是主管才會做的事,對於主管(Director)來說,不需要readReport()這個方法,但卻被迫實作且可以呼叫不會使用的方法,這就違反了ISP原則。

為了符合ISP原則,將code改成如下,將AdminUsage拆的更小:

vocus|新世代的創作平台
vocus|新世代的創作平台

如此一來,秘書可以讀取報表,不需要去實作用不到的審核假單。
主管可以審核假單,不需要去實作用不到的讀取報表,也就符合了ISP原則。


Dependency Inversion Principle(DIP) 依賴反轉原則

  • 高階模組不應該依賴於低階模組,兩者都應該依賴抽象。

例如為了「讀取報表」功能,需要依賴Excel類別的readFile()來讀取檔案,如同下面的程式碼一樣。

vocus|新世代的創作平台

這時候問題就來了,假設要改從Word去讀取檔案,而Word類別的方法名稱不是readFile(), 而是readContent(),高階模組readReport()這邊的程式碼,就會因為低階模組的改動,也需要跟著改程式,這就是所謂的高階模組依賴於低階模組:

vocus|新世代的創作平台

為了符合DIP原則,修改如下:

vocus|新世代的創作平台
vocus|新世代的創作平台

現在變成高階模組跟低階模組都依賴IReader interface,假如今天要換成從PPT讀取呢? 這樣的程式碼擴充就很容易,對我來說只需要新增一個PPT class並且implements IReader 實作readContent() method,然後將PPT instance傳入高階模組建構子即可:

vocus|新世代的創作平台
vocus|新世代的創作平台

有沒有發現,這樣設計後高階模組的code完全不用改,也變相的統一了method name,都叫做readContent(),對於新的低階模組class而言只需把readContent()的邏輯寫好,高階模組會去call readContent(),完全不須改code。

也就是說,想要符合DIP原則,可以朝這樣的方向去思考: 「為了達成這個目的,我需要依賴什麼功能?」將這個功能設計成interface即可

以這個例子而已,為了達成讀取報表的目的,我需要依賴讀取資料的功能,因此把讀取資料功能拉出來設計成介面,讓高低階模組皆依賴於這個介面,即可符合DIP原則。



本筆記參考:

1. https://matthung0807.blogspot.com/2021/01/java-solid-liskov-substitution-principle.html
2. https://www.cnblogs.com/windpoplar/p/12724391.html
3. https://easonchang0115.github.io/blogs/other/2021/20210427_1.html#d-dependency-inversion-principle
4. https://ianjustin39.github.io/ianlife/design-pattern/liskov-substitution-principle/
5. https://medium.com/%E7%A8%8B%E5%BC%8F%E6%84%9B%E5%A5%BD%E8%80%85/%E4%BD%BF%E4%BA%BA%E7%98%8B%E7%8B%82%E7%9A%84-solid-%E5%8E%9F%E5%89%87-%E4%BB%8B%E9%9D%A2%E9%9A%94%E9%9B%A2%E5%8E%9F%E5%89%87-interface-segregation-principle-50f54473c79e
6. https://ithelp.ithome.com.tw/articles/10192464
7. https://notfalse.net/1/dip
8. https://www.jyt0532.com/2020/03/24/dip/
9. https://igouist.github.io/post/2020/12/oo-14-dependency-inversion-principle/



留言
avatar-img
Vic Lin的沙龍
20會員
161內容數
Vic Lin的沙龍的其他內容
2023/08/13
父元件 傳遞方法使用@ <template>    ...    <Login @modalClose="modalClose"/> ... </template> <script setup>     const _modal = ref();     function m
2023/08/13
父元件 傳遞方法使用@ <template>    ...    <Login @modalClose="modalClose"/> ... </template> <script setup>     const _modal = ref();     function m
2023/03/25
前情提要 由於我的筆電已經用了10年,無法再戰下去了,且有預算考量,加上使用電腦幾乎都是定點,只有偶爾回家的時候會需要攜帶,因此最終選擇了迷你電腦,體積小不占空間,又方便攜帶,剛好符合我的需求。 菜單 由於這台無法裝獨顯,所以CPU的部分選擇 AMD R5 3400G(含Vega 11內
Thumbnail
2023/03/25
前情提要 由於我的筆電已經用了10年,無法再戰下去了,且有預算考量,加上使用電腦幾乎都是定點,只有偶爾回家的時候會需要攜帶,因此最終選擇了迷你電腦,體積小不占空間,又方便攜帶,剛好符合我的需求。 菜單 由於這台無法裝獨顯,所以CPU的部分選擇 AMD R5 3400G(含Vega 11內
Thumbnail
2023/03/10
Nuxt3中可使用useFetch來獲取數據,不須再引用axios,相當方便: 本筆記參考: https://juejin.cn/post/7104071421160063012 https://juejin.cn/post/7086472647575339045
2023/03/10
Nuxt3中可使用useFetch來獲取數據,不須再引用axios,相當方便: 本筆記參考: https://juejin.cn/post/7104071421160063012 https://juejin.cn/post/7086472647575339045
看更多
你可能也想看
Thumbnail
你是知識工作者還是產線工作者?真心建議HR真的要學習運算思維,就算對於數位科技與數據分析沒有興趣,也要掌握運算思維的解構化、抽象化、流程化、模式化核心,這對你的解決員工問題能力以及設計出有用的制度相當有幫助。反覆做是電腦的工作,不是知識工作者的工作。
Thumbnail
你是知識工作者還是產線工作者?真心建議HR真的要學習運算思維,就算對於數位科技與數據分析沒有興趣,也要掌握運算思維的解構化、抽象化、流程化、模式化核心,這對你的解決員工問題能力以及設計出有用的制度相當有幫助。反覆做是電腦的工作,不是知識工作者的工作。
Thumbnail
近期花了一些時間研讀 Robert C. Martin 所著的 Clean Architecture 這本書,剛好看到了一些概念恰巧可以與工作上遇到的架構做一些印證,於是便想寫一些文章做一些紀錄。 在 Clean Architecture 中,提到了軟體元件的內聚與耦合的概念。
Thumbnail
近期花了一些時間研讀 Robert C. Martin 所著的 Clean Architecture 這本書,剛好看到了一些概念恰巧可以與工作上遇到的架構做一些印證,於是便想寫一些文章做一些紀錄。 在 Clean Architecture 中,提到了軟體元件的內聚與耦合的概念。
Thumbnail
這本書大概花了一個禮拜的零碎時間看完,其實收穫很多,很多原則不僅僅適用於微服務,也適用在單體式應用被部署在很多節點上,加上跟過去的經驗比較,更能體會到書中的觀點
Thumbnail
這本書大概花了一個禮拜的零碎時間看完,其實收穫很多,很多原則不僅僅適用於微服務,也適用在單體式應用被部署在很多節點上,加上跟過去的經驗比較,更能體會到書中的觀點
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
自今年起,我開始接手了公司的GLP規範之章程的建立,從零開始,到今年也建構了一年,過程中也對流程建立也有些心得,也深刻理解這不是件容易的事情,一方面需要釐清目標與現況資源的差距,在有意義的規範下河有限的資源創造出最可行的規範,是一門專業。此篇跟大家聊聊,如何從零到有。
Thumbnail
自今年起,我開始接手了公司的GLP規範之章程的建立,從零開始,到今年也建構了一年,過程中也對流程建立也有些心得,也深刻理解這不是件容易的事情,一方面需要釐清目標與現況資源的差距,在有意義的規範下河有限的資源創造出最可行的規範,是一門專業。此篇跟大家聊聊,如何從零到有。
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
我們可以利用這些邏輯應用在企畫書、讀書計畫、等等,本質來說這些都是目標設定的學問。另外,操作者也需要完全理解作業流程的方向以及具體的操作,操作者本身也需要定時進修,掌握技術之外,也需要適時反應標準作業流程的問題,或是需要更深入了解設計的意義。不論任何框架,其目的都是要讓理想更具體的能夠執行。
Thumbnail
我們可以利用這些邏輯應用在企畫書、讀書計畫、等等,本質來說這些都是目標設定的學問。另外,操作者也需要完全理解作業流程的方向以及具體的操作,操作者本身也需要定時進修,掌握技術之外,也需要適時反應標準作業流程的問題,或是需要更深入了解設計的意義。不論任何框架,其目的都是要讓理想更具體的能夠執行。
Thumbnail
本筆記除了以文字說明SOLID設計原則以外,並以Java code實際舉例。 Single Responsibility Principle (SRP) 單一職責原則 每個人負責屬於自己的職責,不該承擔太多職責,大家各自做自己應該做的事情,且不會互相干擾。 續上程式碼,修改如下: Output:
Thumbnail
本筆記除了以文字說明SOLID設計原則以外,並以Java code實際舉例。 Single Responsibility Principle (SRP) 單一職責原則 每個人負責屬於自己的職責,不該承擔太多職責,大家各自做自己應該做的事情,且不會互相干擾。 續上程式碼,修改如下: Output:
Thumbnail
SOP是工作中很常聽見的詞,全名叫「標準化製作流程」,主要是讓執行有依據,通常是為了複雜的事而設計的內部程序,對新手來說,SOP 能加快新人的學習速度和降低出錯的機率。可是啊,站在專業服務工作的角度,尤其工作內容是人與人之間需要密切的互動這種類型時,完全照 SOP來,真的是最好的方式嗎?
Thumbnail
SOP是工作中很常聽見的詞,全名叫「標準化製作流程」,主要是讓執行有依據,通常是為了複雜的事而設計的內部程序,對新手來說,SOP 能加快新人的學習速度和降低出錯的機率。可是啊,站在專業服務工作的角度,尤其工作內容是人與人之間需要密切的互動這種類型時,完全照 SOP來,真的是最好的方式嗎?
Thumbnail
「每個工作者,不論是個人還是團隊,都應該把自己當作是管理多個生產線的工廠。」上回寫《如何把工作快狠準搞定?洞悉流程才是關鍵》,意外獲得滿多迴響,決定寫個續篇,來補充一些當時寫完之後想加入的內容。 其中一個想補充的是針對下面這段話: 然後,擴及到去洞悉其他任務、其他工作者、其他內外部組織的工作流程。
Thumbnail
「每個工作者,不論是個人還是團隊,都應該把自己當作是管理多個生產線的工廠。」上回寫《如何把工作快狠準搞定?洞悉流程才是關鍵》,意外獲得滿多迴響,決定寫個續篇,來補充一些當時寫完之後想加入的內容。 其中一個想補充的是針對下面這段話: 然後,擴及到去洞悉其他任務、其他工作者、其他內外部組織的工作流程。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News