1. 概述
装饰器模式可用于静态或动态地将附加职责附加到对象,装饰器为原始对象提供增强的接口。
在这种模式的实现中,我们更倾向于组合而不是继承-这样我们就可以减少为每个装饰元素一次又一次地子类化的开销。这种设计中所涉及的递归可用于根据需要多次装饰我们的对象。
2. 装饰者模式示例
假设我们有一个圣诞树对象,我们想要装饰它。装饰不会改变对象本身;只是除了圣诞树之外,我们还添加了一些装饰品,如花环、金属丝、树顶、泡泡灯等:
对于这种情况,我们将遵循最初的四人帮设计和命名约定。首先,我们将创建一个ChristmasTree接口及其实现:
public interface ChristmasTree {
String decorate();
}
该接口的实现如下所示:
public class ChristmasTreeImpl implements ChristmasTree {
@Override
public String decorate() {
return "Christmas tree";
}
}
现在,我们将为这棵树创建一个抽象的TreeDecorator类,这个装饰器将实现ChristmasTree接口并持有相同的对象,来自同一接口的实现方法将简单地从我们的接口调用decorate()方法:
public abstract class TreeDecorator implements ChristmasTree {
private ChristmasTree tree;
// standard constructors
@Override
public String decorate() {
return tree.decorate();
}
}
我们现在将创建一些装饰元素,这些装饰器将扩展我们的抽象TreeDecorator类,并根据我们的要求修改其decorate()方法:
public class BubbleLights extends TreeDecorator {
public BubbleLights(ChristmasTree tree) {
super(tree);
}
public String decorate() {
return super.decorate() + decorateWithBubbleLights();
}
private String decorateWithBubbleLights() {
return " with Bubble Lights";
}
}
对于这种情况,以下断言为真:
@Test
void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
assertEquals(tree1.decorate(), "Christmas tree with Garland");
ChristmasTree tree2 = new BubbleLights(new Garland(new Garland(new ChristmasTreeImpl())));
assertEquals(tree2.decorate(), "Christmas tree with Garland with Garland with Bubble Lights");
}
请注意,在第一个tree1对象中,我们只用一个Garland来装饰它,而我们用一个BubbleLights和两个Garlands装饰另一个tree2对象。这种模式使我们能够灵活地在运行时添加任意数量的装饰器。
3. 总结
在本文中,我们了解了装饰器设计模式,在以下情况下这是一个不错的选择:
- 当我们希望添加、增强甚至删除对象的行为或状态时
- 当我们只想修改类的单个对象的功能而其他对象保持不变时
与往常一样,本教程的完整源代码可在GitHub上获得。
Show Disqus Comments
Post Directory
扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章