當前位置:才華齋>計算機>java語言>

該怎麼使用Java設計模式程式設計中的OCP開閉原則?

java語言 閱讀(1.28W)

OCP開閉原則定義:一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。

該怎麼使用Java設計模式程式設計中的OCP開閉原則?

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

解決方案:當軟體需要變化時,儘量通過擴充套件軟體實體的行為來實現變化,而不是通過修改已有的程式碼來實現變化。

開閉原則是面向物件設計中最基礎的設計原則,它指導我們如何建立穩定靈活的系統。開閉原則可能是設計模式六項原則中定義最模糊的一個了,它只告訴我們對擴充套件開放,對修改關閉,可是到底如何才能做到對擴充套件開放,對修改關閉,並沒有明確的告訴我們。以前,如果有人告訴我“你進行設計的時候一定要遵守開閉原則”,我會覺的他什麼都沒說,但貌似又什麼都說了。因為開閉原則真的太虛了。

在仔細思考以及仔細閱讀很多設計模式的文章後,終於對開閉原則有了一點認識。其實,我們遵循設計模式前面5大原則,以及使用23種設計模式的目的就是遵循開閉原則。也就是說,只要我們對前面5項原則遵守的好了,設計出的軟體自然是符合開閉原則的,這個開閉原則更像是前面五項原則遵守程度的“平均得分”,前面5項原則遵守的好,平均分自然就高,說明軟體設計開閉原則遵守的好;如果前面5項原則遵守的不好,則說明開閉原則遵守的不好。

其實筆者認為,開閉原則無非就是想表達這樣一層意思:用抽象構建框架,用實現擴充套件細節。因為抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟體架構的穩定。而軟體中易變的細節,我們用從抽象派生的實現類來進行擴充套件,當軟體需要發生變化時,我們只需要根據需求重新派生一個實現類來擴充套件就可以了。當然前提是我們的抽象要合理,要對需求的變更有前瞻性和預見性才行。

在開閉原則的定義中,軟體實體可以指一個軟體模組、一個由多個類組成的區域性結構或一個獨立的類。

任何軟體都需要面臨一個很重要的問題,即它們的需求會隨時間的推移而發生變化。當軟體系統需要面對新的需求時,我們應該儘量保證系統的設計框架是穩定的。如果一個軟體設計符合開閉原則,那麼可以非常方便地對系統進行擴充套件,而且在擴充套件時無須修改現有程式碼,使得軟體系統在擁有適應性和靈活性的同時具備較好的穩定性和延續性。隨著軟體規模越來越大,軟體壽命越來越長,軟體維護成本越來越高,設計滿足開閉原則的軟體系統也變得越來越重要。

為了滿足開閉原則,需要對系統進行抽象化設計,抽象化是開閉原則的關鍵。在Java、C#等程式語言中,可以為系統定義一個相對穩定的抽象層,而將不同的實現行為移至具體的實現層中完成。在很多面向物件程式語言中都提供了介面、抽象類等機制,可以通過它們定義系統的抽象層,再通過具體類來進行擴充套件。如果需要修改系統的行為,無須對抽象層進行任何改動,只需要增加新的具體類來實現新的業務功能即可,實現在不修改已有程式碼的基礎上擴充套件系統的功能,達到開閉原則的要求。

Sunny軟體公司開發的CRM系統可以顯示各種型別的`圖表,如餅狀圖和柱狀圖等,為了支援多種圖表顯示方式,原始設計方案如下圖所示:

在ChartDisplay類的display()方法中存在如下程式碼片段:

...... if (ls("pie")) { PieChart chart = new PieChart(); lay(); } else if (ls("bar")) { BarChart chart = new BarChart(); lay(); } ......

在該程式碼中,如果需要增加一個新的圖表類,如折線圖LineChart,則需要修改ChartDisplay類的display()方法的原始碼,增加新的判斷邏輯,違反了開閉原則。

現對該系統進行重構,使之符合開閉原則。

在本例項中,由於在ChartDisplay類的display()方法中針對每一個圖表類程式設計,因此增加新的圖表類不得不修改原始碼。可以通過抽象化的方式對系統進行重構,使之增加新的圖表類時無須修改原始碼,滿足開閉原則。具體做法如下:

(1) 增加一個抽象圖表類AbstractChart,將各種具體圖表類作為其子類;

(2) ChartDisplay類針對抽象圖表類進行程式設計,由客戶端來決定使用哪種具體圖表。

重構後結構如下圖所示:

在圖2中,我們引入了抽象圖表類AbstractChart,且ChartDisplay針對抽象圖表類進行程式設計,並通過setChart()方法由客戶端來設定例項化的具體圖表物件,在ChartDisplay的display()方法中呼叫chart物件的display()方法顯示圖表。如果需要增加一種新的圖表,如折線圖LineChart,只需要將LineChart也作為AbstractChart的子類,在客戶端向ChartDisplay中注入一個LineChart物件即可,無須修改現有類庫的原始碼。

注意:因為xml和properties等格式的配置檔案是純文字檔案,可以直接通過VI編輯器或記事本進行編輯,且無須編譯,因此在軟體開發中,一般不把對配置檔案的修改認為是對系統原始碼的修改。如果一個系統在擴充套件時只涉及到修改配置檔案,而原有的Java程式碼或C#程式碼沒有做任何修改,該系統即可認為是一個符合開閉原則的系統。