一、什么是裝飾器模式
????????裝飾器模式(Decorator Pattern)是一種結構型設計模式,它的核心思想是在不改變原有對象結構的情況下,動態地給對象增加一些功能,從而達到擴展功能的目的。舉個例子,今天在家媽媽給蒸饅頭。饅頭蒸的過程中,媽媽去收拾衣服了。突然想起來,饅頭好了,就跟你說:“幫我把饅頭拿出來。”這個時候饅頭特別燙,如果不燙其實用我們的手是可以拿出來的,但是這個時候光用手拿不行。所以我們想了個辦法,找了一個手套,從而把饅頭拿了出來。這個過程就類似于裝飾器模式,手套相當于裝飾器,給手(原有對象)增加了隔熱的功能,使得手能夠處理原本無法直接處理的燙饅頭。
二、為什么使用裝飾器模式
? ? ? ? 基于上面的饅頭場景,我們討論一下為什么使用裝飾器模式(為什么要戴手套):
-
動態擴展(撤銷)功能:當需要在運行時為對象動態添加功能時,裝飾器模式是一個很好的選擇。例如,比如應對熱饅頭去拿的時候要隔熱功能,不想隔熱還可以直接上手。但是裝飾的多了,手不熱嗎?手不累嗎?所示要適當添加。別為了拿饅頭裝了一堆東西反而得不償失。
-
避免子類爆炸:如果通過繼承來擴展功能,可能會導致子類數量急劇增加,使得系統變得復雜且難以維護。裝飾器模式可以避免這種情況,通過組合的方式動態添加功能(繼承關系的替代)。
-
保持原有接口不變:裝飾器模式可以在不改變原有對象接口的情況下,增加新的功能,這使得客戶端代碼可以透明地使用被裝飾的對象,而不需要修改客戶端代碼。(拿饅頭的手,拿的功能不變)
三、裝飾器模式示例
-
Component(抽象組件):定義了被裝飾對象的接口,所有具體的組件和裝飾器都實現這個接口。
//我就是一個手,人們定義我叫手,收能拿東西 public interface Hand {void pickUp(Object object) throws Exception; }
-
ConcreteComponent(具體組件):實現了Component接口的具體組件,是被裝飾的對象。
//我是一個赤裸裸真是長在身上的手,人們說手可以拿東西,我也可以 public class BareHand implements Hand {@Overridepublic void pickUp(Object object) throws Exception {if (object instanceof HotBun) {throw new Exception("我擦,太熱了!");}System.out.println("Picked up " + object.getClass().getSimpleName() + " with bare hands.");} }
-
Decorator(裝飾器抽象類):也實現了Component接口,持有一個Component對象的引用,通過組合的方式動態地為Component對象添加新的功能。
//其實手上沒準可以加點東西 public abstract class HandDecorator implements Hand {protected Hand hand;public HandDecorator(Hand hand) {this.hand = hand;}@Overridepublic void pickUp(Object object) throws Exception {hand.pickUp(object);} }
-
ConcreteDecorator(具體裝飾器):實現了Decorator的具體裝飾器,負責給Component對象添加具體的裝飾功能。
//我是手套 public class GloveDecorator extends HandDecorator {public GloveDecorator(Hand hand) {super(hand);}@Overridepublic void pickUp(Object object) throws Exception {System.out.println("戴上手套去拿 " + object.getClass().getSimpleName());hand.pickUp(object);} }
-
客戶端
//我是一個熱饅頭 public class HotBun {// 燙饅頭的具體實現 }
public class Main {public static void main(String[] args) {Hand bareHand = new BareHand();try {bareHand.pickUp(new HotBun());} catch (Exception e) {System.out.println(e.getMessage());}// 使用手套裝飾手Hand glovedHand = new GloveDecorator(bareHand);try {glovedHand.pickUp(new HotBun());} catch (Exception e) {System.out.println(e.getMessage());}} }//輸出 我擦,太熱了! 戴上手套去拿熱饅頭 我擦,太熱了!