一、介紹
開閉原則(OCP) 是面向對象設計中 “可複用設計” 的基石,是面向對象設計中最重要的原則之一,其它很多的設計原則都是實現開閉原則的一種手段。
1988年,勃蘭特·梅耶(Bertrand Meyer)在他的著作《面向對象軟件構造(Object Oriented Software Construction)》中提出了開閉原則,它的原文是這樣:“Software entities should be open for extension,but closed for modification”。
翻譯過來就是:“軟件實體應當對擴展開放,對修改關閉”。這句話說得略微有點專業,我們把它講的更通俗一點,也就是:軟件系統中包含的各種組件,例如模(Modules)、類(Classes)以及功能(Functions)等等,應該在不修改現有代碼的基礎上,涌入新的功能。開閉原則中 “開” ,是指對組件功能的擴展是開放的,是允許對齊進行功能擴展的;開閉原則中 “閉” ,是指對原有代碼的修改是封閉的,即修改原有的代碼對外部的使用時透明的。
二、概述
遵循開閉原則設計出來的魔鎧具有兩個主要特徵:
(1)、對於擴展是開放的(Open for extension)。這意味着模塊的行爲是可以擴展的。當應用的需求改變時,我們可以對模塊的進項擴展,使其具有滿足那些改變的新行爲。也就是說,我們可以改變模塊的功能。
(2)、對於修改是關閉的(Closed for modification)。對模塊行爲進行擴展時,不必改動模塊的源代碼或則二進制代碼。模塊的二進制可執行版本,無論是可連接的庫、DLL或則 .EXE 文件,都無需改動。
三、實現方法
- 抽象約束
第一,通過接口或者抽象類約束擴展,對擴展進行邊界限定,不允許出現在接口或抽象類中不存在的public方法;
第二,參數類型、引用對象儘量使用接口或者抽象類,而不是實現類;
第三,抽象層儘量保持穩定,一旦確定即不允許修改。
- 元數據(metadata)控制模塊行爲
元數據就是用來描述環境和數據的數據,通俗地說就是配置參數,參數可以從文件中獲得,也可以從數據庫中獲得。
Spring容器就是一個典型的元數據控制模塊行爲的例子,其中達到極致的就是控制反轉(Inversion of Control)
- 制定項目章程
在一個團隊中,建立項目章程是非常重要的,因爲章程中指定了所有人員都必須遵守的約定,對項目來說,約定優於配置。
- 封裝變化
對變化的封裝包含兩層含義:
第一,將相同的變化封裝到一個接口或者抽象類中;
第二,將不同的變化封裝到不同的接口或抽象類中,不應該有兩個不同的變化出現在同一個接口或抽象類中。
四、如何靈活使用開閉原則
開閉原則指導我們,當軟件需要變化時,用該儘量通過擴展的方式來實現變化,而不是通過修改已有的代碼來實現。“應該儘量” 說明 OCP原則並不是說絕對不可以修改原始類的。當我們嗅到原來的代碼 “腐化氣味” 時,應該儘早地重構,以便使代碼恢復到正常的 “進化”過程,而不是通過繼承等方式添加新的實現,這會導致類型的膨脹以及歷史遺留代碼的冗餘。我們開發過程中也沒有那麼理想化的狀況,完全地不用修改原來的代碼,因此,在開發過程中需要自己結合具體情況進行考量,是通過修改舊代碼還是通過繼承使得軟件系統更穩定、更靈活,在保證去除
“代碼腐化” 的同時,也保證原有模塊的正確性。
五、開閉原則的好處
- 開閉原則對測試的影響
開閉原則可是保持原有的測試代碼仍然能夠正常運行,我們只需要對擴展的代碼進行測試就可以了。
- 開閉原則可以提高複用性
在面向對象的設計中,所有的邏輯都是從原子邏輯組合而來的,而不是在一個類中獨立實現一個業務邏輯。只有這樣代碼纔可以複用,粒度越小,被複用的可能性就越大。
- 開閉原則可以提高可維護性
- 面向對象開發的要求