物件導向設計原則之開閉原則

Liuwei-Sunny發表於2012-05-05

      開閉原則是物件導向的可複用設計的第一塊基石,它是最重要的物件導向設計原則。開閉原則由Bertrand  Meyer1988年提出,其定義如下:

開閉原則(Open-Closed Principle, OCP):一個軟體實體應當對擴充套件開放,對修改關閉。即軟體實體應儘量在不修改原有程式碼的情況下進行擴充套件。

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

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

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

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

初始設計方案結構圖

      在ChartDisplaydisplay()方法中存在如下程式碼片段:

......
if (type.equals("pie")) {
    PieChart chart = new PieChart();
    chart.display();
}
else if (type.equals("bar")) {
    BarChart chart = new BarChart();
    chart.display();
}
......

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

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

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

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

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

      重構後結構如圖2所示:

圖2 重構後的結構圖

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

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

 【作者:劉偉  http://blog.csdn.net/lovelion

相關文章