深入淺出開放封閉原則 Open-Closed Principle
March 19, 2020這篇文章介紹軟體架構裡面 S.O.L.I.D 中的O (Open-Closed Principle)
這篇文章中大部分的程式碼 參考自SOLID Principles of Object-Oriented Design and Architecture
定義
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
你在講啥 開放到可以擴充 但又要封閉到禁止修改?? 擴充不就是修改嗎
其實擴充跟修改他們針對的對象是不同的 但我們最後再回來解釋這句話 因為這句話實在太難懂了
勇於挑戰權威
現在2020年了 身為一個讀書人 我們不能全盤接收外界的知識 即使這是個有名的Principle 我們應該要去理解這個Principle 然後用我們自己的方式去吸收消化
在我看了眾多文獻/線上課程之後 我比較支持另外兩種說法
1.Vasiliy Zukanov 對於OCP的理解
Depend on stable abstractions and modify system’s behavior by providing different realizations
2.Protected Variation: The Importance of Being Closed
Protected Variation pattern: Identify points of predicted variation and create a stable interface around them.
基本上解法很簡單 就是加一層抽象 在OOP的語言中通常指的是介面或是抽象類別
SalaryCalculator
我們繼續來算算員工的薪水吧
等等 別忘了我們才剛講完SRP 現在 SalaryCalculator 這個類別有超過一個reason to change 違反了SRP 必須把計算稅務的邏輯分開
看起來可愛多了 這樣 SalaryCalculator 就不需要知道 TaxCalculator 是怎麼實作的了
好 SalaryCalculator沒問題 但 TaxCalculator 問題不小 今天要是我要加其他類型的Employee我就必須改我的switch 怎麼辦呢?
沒錯 加一層抽象! 我們讓TaxCalculator變成一個介面
有了這個抽象之後 原本的兩個switch case各自需要一個類別去實作這個抽象
這…. 看起來有點眼熟啊…
我們好像把演算法給封裝了 而且演算法之間可以彼此互換
我們好像把抽象的方法抽離在interface 把實作留給subclass
這個好像是…
答對了 我們在這裡引用了策略模式
這樣改完之後 SalaryCalculator 會變成怎麼樣呢
老話一句 你過來我保證不打死你
你只是把switch從TaxCalculator移到SalaryCalculator而已啊 那如果今天我要加個不同種類的員工 我就要動到SalaryCalculator了 說好的SRP呢
別著急 你仔細看一下這個switch的長相
你可以再靠近一點
你可以再靠近一點點
看完之後告訴我這是什麼 沒錯 工廠 簡單工廠
有了這個工廠之後 SalaryCalculator變成這樣
實在是太簡潔啦
來個架構圖吧
黑箭頭代表依賴 白箭頭代表實作
精美 今天如果有一個新的計算稅率方式 有什麼地方要改呢
1.當然 要有個新的TaxCalculatorX類別
2.TaxCalculatorFactory要知道何時需要生成這個類別
搞定 支持新的TaxCalculator類別就是TaxCalculatorFactory的reason to change
SalaryCalculator完全沒動 TaxCalculator完全沒動
看回OCP
回到我們本章的主題 什麼是OCP呢
先來看Vasiliy Zukanov的版本
Depend on stable abstractions and modify system’s behavior by providing different realizations
TaxCalculator 就是這個stable abstractions 而TaxCalculatorFullTime跟TaxCalculatorContrator就是different realizations
再來看Craig Larman的版本
Protected Variation pattern: Identify points of predicted variation and create a stable interface around them.
predicted variation就是稅金計算的方式 而stable interface就是TaxCalculator
這兩個解釋都已經講得很清楚了 但為了給最元老的OCP尊重 我們還是勉為其難來看一下
Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
這下你終於懂了 close到底是close什麼 就是要有一個不會改變的抽象 open到底是open什麼 就是要能夠提供彈性的實作
所以本文第一段所說 擴充跟修改他們針對的對象是不同的 是這個意思
初初學者友善教學
我想 對於Uncle Bob這種等級的大神 這種概念他們早就已經內化成他們日常生活的一部分 只是為了出書或是教學 把腦中的概念模糊的寫出來 殊不知 初學者根本看不懂你想表達的是什麼
當然我也期許未來的某一天我也可以到達大神境界 但在那之前 我先把我的讀書心得寫下來 讓初學者的心得可以對初初學者的學習有幫助 那就不枉費這篇文章
總結
這篇文章告訴你為什麼一個恰當的抽象 可以讓你的架構多出許多的彈性
那為什麼這篇文章還提到了工廠模式跟策略模式呢
再重申一次 SOLID 只是一個心法 而工廠模式跟策略模式這兩個是我們用來遵循OCP的手段
就像你想要殺死被生死蟲感染的殭屍 我跟你說他只要頭沒了就掛了(心法) 那你是要用刀砍斷(手段1) 還是用火槍爆頭(手段2)隨你高興