裝飾圖案是廣泛使用的結構圖案之一。 此模式在運行時動態更改對象的功能,而不會影響對象的現有功能。 簡而言之,此模式通過包裝將附加功能添加到對象。
問題陳述:
想像一下我們有一個比薩餅,該比薩餅已經用番茄和奶酪烤制的情況。 之后,您只需要記住,您需要根據客戶的選擇添加一些其他澆頭。 因此,您需要在旅途中再添加一些配料,例如雞肉和胡椒粉。
意圖:
動態地從對象中添加或刪除其他功能或職責,而不會影響原始對象。
有時需要在無法通過子類添加功能的情況下進行,因為這可能會創建子類的負??載。
解:
因此,在這種情況下,我們不是在使用繼承為對象(例如披薩)添加其他功能,而是在使用合成。 當我們不想使用繼承而是使用組合時,此模式很有用。
結構體
裝飾器設計模式結構
以下是“裝飾器設計”模式的參與者:
- 組件 –這是包裝程序,在運行時可以承擔與其相關的其他職責。
- 具體組件 –是添加了附加功能的原始對象。
- 裝飾器 -這是一個抽象類,其中包含對組件對象的引用,并且還實現了組件接口。
- 具體的裝飾器 -它們擴展了裝飾器并在Component類的頂部構建了附加功能。
例:
裝飾器設計模式示例
在上面的示例中,Pizza類充當Component,BasicPizza是需要裝飾的具體組件。 PizzaDecorator充當Decorator抽象類,其中包含對Pizza類的引用。 ChickenTikkaPizza是ConcreteDecorator,它為Pizza類構建了附加功能。
讓我們總結一下實現裝飾器設計模式的步驟:
- 創建一個我們要裝飾的BasicPizza(混凝土組件)的接口。
- 創建一個抽象類PizzaDecorator,其中包含Pizza(decorated)接口的引用字段。
- 注意:裝飾器(PizzaDecorator)必須擴展相同的裝飾(Pizza)接口。
- 現在,我們需要在decorator的構造函數中傳遞要裝飾的Pizza對象。
- 讓我們創建混凝土裝飾器(ChickenTikkaPizza),它應該提供附加澆筑的附加功能。
- Concrete Decorator(ChickenTikkaPizza)應該擴展PizzaDecorator抽象類。
- 將裝飾器(bakePizza())的方法重定向到裝飾類的核心實現。
- 覆蓋需要更改行為的方法(bakePizza()),例如添加Chicken Tikka澆頭。
- 讓客戶端類通過在Concrete Component(BasicPizza)的幫助下創建Concrete Decorator(ChickenTikkaPizza)來創建Component type(Pizza)對象。
- 簡而言之:新組件=混凝土組件+混凝土裝飾器
比薩披薩=新的ChickenTikkaPizza(新的BasicPizza());
代碼示例:
BasicPizza.java
public String bakePizza() {return 'Basic Pizza';}
Pizza.java
public interface Pizza {public String bakePizza();
}
PizzaDecorator.java
public abstract class PizzaDecorator implements Pizza {Pizza pizza;public PizzaDecorator(Pizza newPizza) {this.pizza = newPizza;}@Overridepublic String bakePizza() {return pizza.bakePizza();}
}
ChickenTikkaPizza.java
public class ChickenTikkaPizza extends PizzaDecorator {public ChickenTikkaPizza(Pizza newPizza) {super(newPizza);}public String bakePizza() {return pizza.bakePizza() + ' with Chicken topping added';}
}
客戶端程序
public static void main(String[] args) {Pizza pizza = new ChickenTikkaPizza(new BasicPizza());System.out.println(pizza.bakePizza());}
優點:
裝飾器設計模式比標準繼承提供了更大的靈活性。 繼承還以靜態方式擴展了父類責任。 但是裝飾器允許以動態方式執行此操作。
退稅:
代碼調試可能很困難,因為此模式會在運行時添加功能。
有趣的一點:
- 適配器模式將不同的接口插入在一起,而裝飾器模式則增強了對象的功能。
- 與裝飾器模式不同,策略模式無需更改即可更改原始對象。
- 代理模式控制對對象的訪問時,裝飾器模式增強了對象的功能。
- Composite和Decorator模式都使用相同的樹結構,但兩者之間存在細微的差異。 當我們需要將具有相似行為的一組對象保留在另一個對象中時,可以使用復合模式。 但是,當我們需要在運行時修改對象的功能時,會使用裝飾器模式。
- Java API中有許多裝飾器模式的實時示例。
- java.io.BufferedReader;
如果我們看到了BufferedReader的構造函數,那么我們可以看到BufferedReader通過添加更多功能(例如,在reader類中不存在的readLine())包裝了Reader類。
我們可以使用與上述示例相同的格式來說明客戶端如何使用修飾符模式new BufferedReader(new FileReader(new File(“ File1.txt”)));
同樣, BufferedInputStream是裝飾對象FileInputStream的裝飾器。
BufferedInputStream bs = new BufferedInputStream(new FileInputStream(new File(“ File1.txt”))));
參考: 四人幫–在Idiotechie博客上使用JCG合作伙伴 Mainak Goswami的裝飾設計圖案進行裝飾 。
翻譯自: https://www.javacodegeeks.com/2012/12/decorate-with-decorator-design-pattern.html