動態(組合)地給一個對象增長一些額外的職責。就增長功能而言,Decorator 模式比生成子類(繼承)更爲靈活(消除重複代碼 & 減小子類個數)。——《設計模式》GoFjava
若是在代碼中出現以下相似代碼:git
public class ClassA implements InterfaceA { InterfaceA a; // ... }
一個類既實現了 InterfaceA
接口,又包含 InterfaceA
字段,那麼在這段代碼的位置,幾乎能夠確定使用了裝飾器模式。其中,實現 InterfaceA
是爲了確保 ClassA
保留 InterfaceA
接口的規範,而包含 InterfaceA
字段是爲了利用組合實現多態。github
裝飾器,顧名思義,須要裝飾誰?這個「誰」就是裝飾器模式的主體,這個主體的具體實現通常會有規範它行爲特質的接口(接口就是規範),咱們能夠經過實現這個接口添加一個抽象裝飾器(爲了進一步的擴展裝飾器的能力,因此這個裝飾器爲抽象的,或者稱之爲非葉子節點的,非最終使用的裝飾器),當須要爲主體對象擴展某些功能或者附加某些責任時,再建立具體的裝飾器對象去繼承上面的抽象裝飾器,達到擴展主體對象功能或附加責任的目的。綜上,代碼設計思路以下:設計模式
明確須要裝飾(擴展、附加責任)的主體對象如 ClassA
,示例代碼以下:ide
public class ClassA { @Override public void eat() { System.out.println("吃飯"); } }
抽象出該主體對象的接口(規範)如 InterfaceA
,示例代碼以下:測試
public interface InterfaceA { void eat(); }
建立抽象裝飾器如 DecoratorA
,示例代碼以下(裝飾器模式顯著代碼特徵):this
public abstract class DecoratorA implements InterfactA { protected InterfaceA interfaceA; }
建立具體的裝飾器,用來擴展主體對象的功能,如 ConcreteDecoratorA
,示例代碼以下:spa
public class ConcreteDecoratorA extends DecoratorA { public ConcreteDecoratorA (InterfaceA interfaceA) { this.interfaceA = interfaceA; } // 下方重寫 `override` InterfaceA 中的方法,作功能增強 @Override public void eat() { // 功能增強 System.out.println("飯前洗手"); // 調用主體類方法,執行功能 this.interfaceA.eat(); // 功能增強 System.out.println("飯後洗手"); } }
測試示例代碼以下:設計
@Test public void concreteDecoratorTest() { // 不使用裝飾器 System.out.println("不使用裝飾器:"); InterfaceA classA = new ClassA(); classA.eat(); System.out.println(); System.out.println("-------------------------------------------"); System.out.println(); // 使用裝飾器 System.out.println("使用裝飾器:"); InterfaceA concreteDecoratorA = new ConcreteDecoratorA(new ClassA()); concreteDecoratorA.eat(); }
輸出以下所示:code
不使用裝飾器: 吃飯 ------------------------------------------- 使用裝飾器: 飯前洗手 吃飯 飯後洗手
模擬小明「吃飯」和「找對象」場景: