抽象和封裝

關鍵字: 抽象和封裝
二.抽象和封裝 
整理自 《java與模式》閻宏編著 

1.關於抽象類 
    只要有可能,不要從具體類繼承。 
     
    如圖,在一個以繼承關係形成的等級結構裏面,樹葉節點應該是具體類,而樹枝節點應該是抽象類或接口。 
    抽象類應該擁有儘可能多的共同代碼。 
     
    抽象類應該擁有儘可能少的數據。 
     
    在一個繼承的等級結構中,共同的代碼應該儘可能的往等級結構的上方移動。把重複的代碼從子類移到超類中,可以提高代碼的複用率。一個對象從超類繼承過來的代碼,在不使用時不會造成對資源的浪費。   
    一個對象的數據,無論是否使用都會佔用資源,因此數據應該儘量放到具體類或等級結構的低端。 
    
    

2.對可變性封裝原則 
    “找到系統的可變因素,將它封裝起來”,稱爲可可變性封裝原則,是實現“開-閉”原則的途徑,與合成/聚集複用原則相輔相成。 
     抽象化與實現化的最簡單實現,也就是“開-閉”原則在類層次上的最簡單的實現,如下圖所示: 
     
    一般來說,一個繼承結構中的第一層是抽象角色,封裝了抽象的商業邏輯,這是系統中不變的部分。第二層是實現角色,封裝了設計中會變化的因素。這個實現允許實現化角色有多態性變化。如下圖所示: 
     
    換言之,客戶端可以持有抽象化類型的對象,而不在意對象的真實類型是“實現化”、“實現化1”、“實現化2”、“實現化3”。如下圖所示: 
     
    顯然,每一個繼承關係都封裝了一個變化因素,而一個繼承關係不應當同時處理兩個變化因素。換言之,這種簡單實現不能夠處理抽象化與實現化都面臨變化的情況。如下圖所示: 
     
    上圖中的兩個變化因素應當是彼此獨立的,可以在不影響另一者的情況下獨立演化。比如,下面的兩個等級結構分別封裝了自己的變化因素,由於每一個變化因素都是可以通過靜態關係表達的,因此分別使用繼承關係實現,如下圖所示: 
     
    那麼在抽象化與實現化之間的變化怎麼辦? 
    正確的設計方案應當是使用兩個獨立的等級結構封裝兩個獨立的變化因素,並且在它們之間使用聚合關係,以達到功能複合的目的。自然地引導到橋接模式上面。如下圖所示: 
           
    從另一個角度講,一個好的設計通常沒有多於兩層的繼承等級結構。或者說,如果出現了兩個以上的變化因素,就需要找出哪一個變化因素是靜態的,可以使用繼承關係;哪一個變化因素是動態的,可以使用聚合關係。 



3.接口 
    接口只定義了方法的特徵,而沒有給出具體的實現。由於接口沒有給出任何實現,所以它比抽象類更爲抽象。 
    接口是軟件可插撥性(pluggable)的保證。 
    在一個類等級結構中的任何一個類都可以實現一個接口。這個接口會影響到此類的所有子類。此類不得不實現這個接口中所規定的方法,而其子類自動繼承到這些方法,也可以置換掉這些方法(或者其中一些方法)。這時候,這些子類就具有了可插撥性。 
    關聯的可插撥性: 
    一個對象需要完成一項任務,所以需要知道其它對象,並調用其它對象的方法。這個對象對其它對象的知識叫做關聯。 
如果一個關聯不是針對一個具體的類, 而是針對一個接口,那麼任何實現這個接口的類都可以滿足要求。換句話說,當前對象並不在意關聯的是那一個具體的類,而僅僅關心這個類是否實現了某個接口。 
這樣就可以動態地將這個關聯從一個具體的類轉換成另外一個具體的類,這麼做的惟一條件是它們實現了相同的接口。 
    調用的可插撥性: 
    一個對象不可避免地調用其它對象的方法,這種調用不一定非得是一個具體的類,而可以是接口,這樣一來,所以實現這個接口的具體類都可以被當前對象調用。而當前對象可以動態地決定調用哪一個具體類的實例。 
因此接口提供了關聯和方法調用的可插撥性,使得軟件在靈活性,可擴展性,可插撥性得到了保證。 
發佈了6 篇原創文章 · 獲贊 2 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章