上一篇文章中,我們提到OO中複用的方式有兩種,組合和繼承。一般情況下,應該儘可能使用組合的方式。現在以複用爲基本需求,推演若干常見組合型模式
1. Decorator模式
需求:我們已經有一羣對象,現在想統一爲這些對象添加若干新特性。更重要的是,這些新特性可以反覆疊加於某個對象,或者只選擇部分特性作用於某個對象。
條件:如果這個特性的實現不依賴於具體的對象,就如同添加一個裝飾,那麼可以應用Decorator模式。
如果基於開閉原則出發,實際上就是要求不修改已有的對象,通過爲每一個新特性實現一個Decorator類來實現擴展(使用的方式是組合)。
應該說:Decorator的使用條件是異常苛刻的,因爲每一個Decorator類要求可裝飾於任意的對象,這些對象可以是現在已經存在的,同時包括那些未來時的。
2. Proxy模式
Proxy模式有點類似於Decorator模式,也是爲已有類的行爲做些新的裝飾。所不同的是,Proxy模式一般只是爲一個對象作裝飾,且這些裝飾不會相互組合疊加。
從開閉原則出發,Proxy與Decorator模式相同,都是要求不修改已有的對象,通過組合的方式,新建一個Proxy類來擴展原有對象的功能。
Proxy模式是典型的中間層技術,以Proxy對象作爲中間層,代替原始對象,從而提供一種更靈活的設計方式。
對代理模式,常見的應用情景是權限和訪問控制:
1) 遠程代理(Remote Proxy)爲一個位於不同的地址空間的對象提供一個本地的代理對象。這個不同的地址空間可以是在同一臺主機中,也可是在另一臺主機中,遠程代理又叫做大使(Ambassador)。
2) 虛擬代理(Virtual Proxy)根據需要創建開銷很大的對象。如果需要創建一個資源消耗較大的對象,先創建一個消耗相對較小的對象來表示,真實對象只在需要時纔會被真正創建。
3) 保護代理(Protection Proxy)控制對原始對象的訪問。保護代理用於對象應該有不同的訪問權限的時候。
4) 智能指引(Smart Reference)取代了簡單的指針,它在訪問對象時執行一些附加操作。
5) Copy-on-Write代理:它是虛擬代理的一種,把複製(克隆)操作延遲到只有在客戶端真正需要時才執行。
3. Decorator模式 /Proxy模式與重構
如果原始代碼沒有使用Decorator模式 /Proxy模式,那麼大多數情況下基本是使用了繼承+多態的方式實現,就這種情況而言,可以使用Replace Inheritance with Delegate重構方法。
最後想說明的是,
1. 這兩個模式的應用時機
雖然這兩個模式是都是裝飾已有對象的行爲,但是一般設計之初我們可能就已經有意的引入這兩個模式。
2. 爲什麼不是多態,而是組合
首先,使用多態總是可以實現需求的,但正如之前文章中所論述的,應該儘可能使用組合。
第二,這兩個模式的主要特點是裝飾,通過裝飾,將對象的主要行爲由原始對象體現,將對象的一些別緻行爲由裝飾對象或者代理對象實現。
這樣的設計更滿足單一職責原則。
3. 爲什麼說是裝飾已有行爲?
沒有增加新的接口;改變了原有接口的效果;