《Java與模式》筆記
第四章 “開-閉”原則(OCP)
OCP:Open-ClosedPrinciple,說一個軟體實體應該對擴充開放,對修改關閉,最早由BertrandMeyer提出,原文:Softwareentities should be open for extension, but closed for modification. OCP被認為是物件導向的可複用設計的第一塊基石。
軟體系統面臨新的需求時,系統的設計必須是穩定的,應該具有兩個特性:
Ø 通過擴充已有的軟體系統,可以提供新的行為功能,滿足對軟體的新需求,使變化中的軟體系統有一定的適應性和靈活性。
Ø 已有的軟體模組,特別是最重要的抽象層模組不能再修改,這就使變化中的軟體系統有一定的穩定性和延續性。
抽象化很關鍵
Java中,可以給出一個或多個抽象Java類或Java介面,規定出所有的具體類必須提供的方法的特徵作為系統的抽象層。這個抽象層預見了所有的可能擴充,因此在任何情況下都不會改變。這就使的系統抽象層不需要修改。
對可變性的封裝
找出系統的可變因素,將其封裝起來。
Ø 一種可變性不應當散落在代碼的很多角落裡,而應當被封裝到一個對象裡面。繼承真正的意義是封裝可變因素,而不該被認為是從一般對象產生特殊對象的方法。
Ø 一種可變性不應當和另一種可變性混合在一起。類圖的繼承結構一般不超過兩層,否則就存在不同可變性混合。
很多情況下,無法百分百做到“開閉原則”,但應當努力按此原則設計,可以顯著改善一個系統的結構。
促成開閉原則OCP
一、裡氏代換原則:任何基類出現的地方可以用子類代替
二、依賴倒轉原則:依賴與抽象,不依賴與實現
三、合成/彙總複用原則:盡量使用合成/彙總來達成複用的目的,而不是繼承關係
四、迪米特法則:一個軟體實體應當儘可能少的和其他實體發生相互作用
五、介面隔離原則:應當給用戶端提供儘可能小的介面,而不是提供大的總介面
其他設計模式促成OCP
Ø 簡單工廠
Ø Factory 方法
Ø 抽象工廠
Ø 構造模式
Ø 橋樑模式
Ø 門面模式
Ø 調停者模式
Ø 訪問者模式
Ø 迭代子模式
Java介面
介面是實現組件的可插入性(Pluggability)的關鍵。
Java介面比抽象類別更抽象,介面的方法必須是抽象的和公開的,不能有構造子。Java介面可以有public、靜態和final的屬性。
沒有介面無法徹底的實現可插入性。使用抽象類別可以實現一定程度的可插入性,但是Java中的類繼承只能是單繼承。在一個“超類—子類”的兩層結構中,如果要讓子類繼承更多的超類特性,要麼修改超類代碼,但是這明顯不明智。那麼就只好在超類上面再次添加超類,形成3層結構,但是如果超類上面的位置已經存在超類了,那隻有往上層挪,最糟糕的情況要挪到最頂端,那就相當於是整個等級結構的修改了。而如果在某一層,超類是有其他供應商提供的,就無法修改了,或者某個新的超類要挪到java.lang.Object頂上,怎麼可能?
所以,只有介面才可以實現真正的可插入性,因為介面支援多實現。
調用和關聯的可插入性:一個對象要完成某個任務,有時需要藉助於其他對象,調用其方法,這種對象這件的關係就是關聯。如果對象只是關心另一個對象是否實現了某介面,那麼這就可以實現關聯的可插入性。
儘可能的用介面或抽象類別進行變數的聲明,參量的型別宣告,方法傳回值型別宣告,而不是使用具體類。而且儘可能的使用介面,而不是抽象類別。理想情況下,具體Java類只實現Java介面和抽象Java中聲明的方法,而不應當給出多餘的方法。
抽象類別
抽象類別基於模板的設計思想。抽象類別是某個類型的部分實現,可以有執行個體變數,一個或多個構造子,可以同時存在抽象方法和具體方法。
抽象類別不能執行個體化對象,具體子類必須具體實現所有的抽象父類的抽象方法,否則子類也抽象。
設計抽象類別的目的一定是用來被繼承的,而具體類不是用來繼承的。如果兩個具體類之間需要有 繼承關係,可以重構為:兩個具體類為兄弟,繼承同一抽象類別。這將符合裡氏代換。
為了最大限度的複用,應當儘可能多的從子類中提取共同點,放到抽象父類中。
具體資料應當盡量放到具體類中,而不應放到頂端的抽象父類中。
面向介面,面向抽象編程。