装饰图案是广泛使用的结构图案之一。 此模式在运行时动态更改对象的功能,而不会影响对象的现有功能。 简而言之,此模式通过包装将附加功能添加到对象。
问题陈述:
想像一下我们有一个比萨饼,该比萨饼已经用番茄和奶酪烤制的情况。 之后,您只需要记住,您需要根据客户的选择添加一些其他浇头。 因此,您需要在旅途中再添加一些配料,例如鸡肉和胡椒粉。
意图:
动态地从对象中添加或删除其他功能或职责,而不会影响原始对象。
有时需要在无法通过子类添加功能的情况下进行,因为这可能会创建子类的负载。
解:
因此,在这种情况下,我们不是在使用继承为对象(例如披萨)添加其他功能,而是在使用合成。 当我们不想使用继承而是使用组合时,此模式很有用。
结构体
以下是“装饰器设计”模式的参与者:
- 组件 –这是包装程序,在运行时可以承担与其相关的其他职责。
- 具体组件 –是添加了附加功能的原始对象。
- 装饰器 -这是一个抽象类,其中包含对组件对象的引用,并且还实现了组件接口。
- 具体的装饰器 -它们扩展了装饰器并在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