設計原則之開閉原則


定義:一個軟件實體(類、模塊或函數)應當對擴展開放,對修改關閉。
   也就是說軟件實體應盡量在不修改原有代碼的情況下進行擴展。

問題:在軟件的生命周期內,因為變化、升級和維護等原因需要對軟件原有代碼進行修改時,可能會給舊代碼中引入錯誤,
   也可能會使我們不得不對整個功能進行重構,並且需要重新測試。

方案:當軟件需要變化時,盡量通過擴展軟件實體的行為來實現變化,而不是通過修改已有的代碼來實現變化。

舉個栗子:這是一個包工頭和工人的故事。。。

情況一:包工頭給工人命名編號。具體實現方式如下:

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. 開閉原則是總綱,要求對擴展開發,對修改關閉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM