裝飾者模式(Decorate)
——給愛用繼承的人一個全新的設計眼界
* 儘管繼承威力強大,但是並不總是能夠實現最有彈性和最好維護的設計。利用組合和委託可以在運行時具有繼承行爲的效果。
* 利用繼承設計子類的行爲,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行爲。然而,如果能夠利用組合的做法擴展對象的行爲,就可以在運行時動態地進行擴展。
* 代碼應該如同晚霞中的蓮花一樣地關閉(免於改變),如同晨曦中的蓮花一樣地開發(能夠擴展)。
設計原則
* 類應該對擴展開放,對修改關閉。
* 我們的目標是允許類容易擴展,在不修改現有代碼的情況下,就可搭配新的行爲。這樣的設計具有彈性可以應對改變,可以接受新的功能來應對改變的需求。
* 在選擇需要被擴展的代碼部分時要小心。每個地方都採用開放-關閉原則,是一種浪費,也沒必要,還會導致代碼變得複雜且難以理解。
裝飾者模式
* 裝飾者模式動態地將責任附件到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案
* 裝飾者和被裝飾者對象有相同的超類型
* 可以用一個或多個裝飾者包裝一個對象
* 既然裝飾者和被裝飾者具有相同的超類型,所以在任何需要院士對象(被包裝)的場合,可以用裝飾過的對象代替
* 裝飾者可以在所委託被裝飾者的行爲之前或之後,加上自己的行爲,以達到特定的目的
* 對象可以在任何時候被裝飾,所以可以在運行時動態的、不限量地用裝飾者來裝飾對象
要點
* 繼承屬於擴展形式之一,但不見得是達到彈性設計的最佳方法
* 在我們的設計中,應該允許行爲可以被擴展,而無須修改現有代碼
* 組合和委託可用於在運行時動態地加上新的行爲
* 除了繼承,裝飾者模式也可以讓我們擴展行爲
* 裝飾者模式意味着一羣裝飾者類,這些類用來包裝具體組件
* 裝飾者反映出被裝飾的組件類型
* 裝飾者可以在被裝飾者的行爲前面或後面加上自己的行爲,甚至將被裝飾者的行爲整個取代掉,而達到特定的目的
* 可以用無數個裝飾者包裝一個組件
* 裝飾者一般對組件的客戶是透明的,除非客戶程序依賴於組件的具體類型
* 裝飾者會導致設計中出現許多小對象,如果過度使用,會讓程序變得很複雜