定義:一個軟體實體(類、子產品或函數)應當對擴充開放,對修改關閉。
也就是說軟體實體應盡量在不修改原有代碼的情況下進行擴充。
問題:在軟體的生命周期内,因為變化、更新和維護等原因需要對軟體原有代碼進行修改時,可能會給舊代碼中引入錯誤,
也可能會使我們不得不對整個功能進行重構,并且需要重新測試。
方案:當軟體需要變化時,盡量通過擴充軟體實體的行為來實作變化,而不是通過修改已有的代碼來實作變化。
舉個栗子:這是一個包工頭和勞工的故事。。。
情況一:包工頭給勞工命名編号。具體實作方式如下:
1. 建立一個勞工接口IWorker,包含一個勞工編号的方法。代碼如下:

2. 建立一個勞工類Worker,來實作上面的IWorker接口方法。代碼如下:
3. 建立一個包工頭類Manager,包含一個給勞工命名編号的方法,依賴IWorker接口。代碼如下:
4. 在類OCPFragment中使用Worker對象調用命名編号的方法來實作功能。代碼如下:
5. 運作後的效果,如下:
以上的實作方式,成功完成了給勞工命名編号的方法。現在我們要新增一個給勞工配置設定角色和任務的功能,如果在現有代碼的基礎上作修改的話,比如在IWorker接口新增勞工角色role()和勞工任務doing()兩個方法,在勞工類Worker中去實作,修改包工頭類Manager中的nameWorker()方法,這樣做,如果多處調用了nameWorker()方法的話,很可能會造成原有功能發生故障,是以這時我們必須遵守開閉原則,對修改關閉、對擴充開發,不去修改原有的nameWorker()方法,而是去新增一個專門用于給勞工配置設定角色和任務的方法,這樣不僅不會影響到原有的功能,還提高了代碼的複用性,更加靈活。
情況二:包工頭給勞工命名編号,給勞工配置設定角色和任務。遵守開閉原則,具體實作方式如下:
1. 在IWorker接口中新增勞工角色role()和勞工任務doing()兩個方法。代碼如下:
2. 勞工類Worker需要去實作新增的兩個方法。代碼如下:
3. 在包工頭類Manager中新增一個給勞工配置設定角色和任務的方法,依然依賴IWorker接口。代碼如下:
4. 在類OCPFragment中仍使用Worker對象去調用allocateTask()方法來實作功能。代碼如下:
5. 運作後的效果,如下:
綜上所述,如果一個軟體系統符合開閉原則,那麼從軟體工程的角度來看,它将具有可複用性好和可維護性好兩大特點。開閉原則是面向對象設計中“可複用設計”的基石,是面向對象設計中最重要的原則之一。
原則:
1. 通過接口或抽象類限制擴充,對擴充進行邊界限定;
2. 參數類型、引用對象盡量使用接口或者抽象類,而不是實作類;
3. 抽象層盡量保持穩定,一旦确定就不允許修改;
4. 将相同的變化封裝在一個接口或抽象類中;
5. 将不同的變化封裝到不同的接口或抽象類中。
總結:
1. 單一職責原則要求實作類要職責單一;
2. 裡氏替換原則要求不要去破壞繼承系統;
3. 依賴倒置原則要求面向接口程式設計;
4. 接口隔離原則要求在設計接口的時候要精簡單一;
5. 迪米特法則要求要降低耦合;
6. 開閉原則是總綱,要求對擴充開發,對修改關閉。
轉載于:https://www.cnblogs.com/chenxkang/p/6669382.html