開放-封閉原則:Software Entities Should Be Open For Extension, Yet Closed For Modification

http://www.textcn.com/jishuwz/prosj/netnet/200612/55186.html

大家可能都有這樣的體會,要滿足各種各樣的客戶,并且客戶的需求經(jīng)常變化,程序員就是這樣的辛苦命,整天改過來改過去,特別用一些非面向?qū)ο蟮恼Z言寫的代碼,函數(shù)的參數(shù)變得越來越長,里面的Case情況慢慢增加,函數(shù)變得很大。軟件幾年之后就變得難于理解和維護(hù),軟件的生命周期好像就要終止。如果能夠擴(kuò)展模塊的功能,同時又不修改原來已經(jīng)測試通過的代碼,那多好啊!

這完全是可以實現(xiàn)的,關(guān)鍵是抽象。把可能的變化用抽象來隔離它。面向接口編程,而不是面向?qū)ο缶幊蹋茉鰪?qiáng)程序的靈活性;如Client類調(diào)用Server 類,如果我們希望Client對象使用另外一個不通的Server對象,就必須修改Client中使用Server類的地方;如果Client調(diào)用 Server的接口就可以避免這種修改,只要生成新的接口實現(xiàn)類,修改Main等初次使用新子類的地方而不需要修改Client類;使用Strategy 模式和Template Method模式是滿足OCP的最常用方法。

如果需要適應(yīng)某種變化就需要對這種變化進(jìn)行抽象,會增加程序的復(fù)雜度。所以設(shè)計人員應(yīng)該熟悉業(yè)務(wù)和了解客戶需求,預(yù)測到需要進(jìn)行抽象的變化。

敏捷建模不建議提前進(jìn)行各種假想的變化抽象,而是當(dāng)變化發(fā)生第一次的時候抽象這種變化,以后同樣的變化就變得很容易。對代碼進(jìn)行重構(gòu)以保持良好的結(jié)構(gòu)是很重要的,每次抽象都不應(yīng)該使軟件變得越來越僵化。這是非面向?qū)ο蟮恼Z言不具備的優(yōu)勢。

 

參考:Health King的專欄

http://blog.csdn.net/kxy/archive/2005/06/27/405013.aspx

滿足OCP的設(shè)計給系統(tǒng)帶來兩個無可比擬的優(yōu)越性.

  • 通過擴(kuò)展已有的軟件系統(tǒng),可以提供新的行為,以滿足對軟件的新需求,使變化中的軟件系統(tǒng)有一定的適應(yīng)性和靈活性.
  • 已有的軟件模塊,特別是最重要的抽象層模塊不能再修改,這就使變化中的軟件系統(tǒng)有一定的穩(wěn)定性和延續(xù)性.

具有這兩個優(yōu)點的軟件系統(tǒng)是一個高層次上實現(xiàn)了復(fù)用的系統(tǒng),也是一個易于維護(hù)的系統(tǒng).那么,我們?nèi)绾尾拍茏龅竭@個原則呢?不能修改而可以擴(kuò)展,這個看起來是自相矛盾的.其實這個是可以做到的,按面向?qū)ο蟮恼f法,這個就是不允許更改系統(tǒng)的抽象層,而允許擴(kuò)展的是系統(tǒng)的實現(xiàn)層.

解決問題的關(guān)鍵在:抽象化.我們讓模塊依賴于一個固定的抽象體,這樣它就是不可以修改的;同時,通過這個抽象體派生,我們就可以擴(kuò)展此模塊的行為功能.如此,這樣設(shè)計的程序只通過增加代碼來變化而不是通過更改現(xiàn)有代碼來變化,前面提到的修改的副作用就沒有了.

      "開-閉"原則如果從另外一個角度講述,就是所謂的"對可變性封裝原則"(Principle of Encapsulation of Variation, EVP).講的是找到一個系統(tǒng)的可變因素,將之封裝起來.在我們考慮一個系統(tǒng)的時候,我們不要把關(guān)注的焦點放在什么會導(dǎo)致設(shè)計發(fā)生變化上,而是考慮允許什么發(fā)生變化而不讓這一變化導(dǎo)致重新設(shè)計.也就是說,我們要積極的面對變化,積極的包容變化,而不是逃避.

      [SHALL01]將這一思想用一句話總結(jié)為:"找到一個系統(tǒng)的可變因素,將它封裝起來",并將它命名為"對可變性的封裝原則".

      "對可變性的封裝原則"意味者兩點:

  1. 一種可變性應(yīng)當(dāng)被封裝到一個對象里面,而不應(yīng)當(dāng)散落到代碼的很多角落里面.同一種可變性的不同表象意味著同一個繼承等級結(jié)構(gòu)中的具體子類.繼承應(yīng)當(dāng)被看做是封裝變化的方法,而不應(yīng)當(dāng)是被認(rèn)為從一般的對象生成特殊的對象的方法(繼承經(jīng)常被濫用).
  2. 一種可變性不應(yīng)當(dāng)與另外一種可變性混合在一起.從具體的類圖來看,如果繼承結(jié)構(gòu)超過了兩層,那么就意味著將兩種不同的可變性混合在了一起.

      "對可變性的封裝原則"從工程的角度說明了如何實現(xiàn)OCP.如果按照這個原則來設(shè)計,那么系統(tǒng)就應(yīng)當(dāng)是遵守OCP的.

      但是現(xiàn)實往往是殘酷的,我們不可能100%的遵守OCP,但是我們要向這個目標(biāo)來靠近.設(shè)計者要對設(shè)計的模塊對何種變化封閉做出選擇.