1. 概述
✅ 装饰器模式(Decorator Pattern) 可以在运行时为对象添加额外的功能,无论是静态还是动态的。它提供了一种比继承更灵活的方式,在不修改原始类的情况下增强对象的行为。
这个模式的核心思想是:组合优于继承。通过递归式的包装结构,我们可以一层层地给对象“加料”,而不需要为每一种组合都创建一个子类。
2. 装饰器模式示例
我们以一棵圣诞树为例。假设我们要对这棵树进行装饰,比如加上彩带、亮片、星星、灯泡等。这些装饰并不会改变树本身,只是让它看起来更漂亮。
在这个场景中,我们将遵循《设计模式:可复用面向对象软件的基础》(Gang of Four)中的命名规范和结构。
2.1 定义基础组件接口
首先定义 ChristmasTree
接口:
public interface ChristmasTree {
String decorate();
}
接着是它的默认实现:
public class ChristmasTreeImpl implements ChristmasTree {
@Override
public String decorate() {
return "Christmas tree";
}
}
2.2 创建抽象装饰器
然后创建一个抽象装饰器类 TreeDecorator
,它实现了 ChristmasTree
接口,并持有一个 ChristmasTree
实例:
public abstract class TreeDecorator implements ChristmasTree {
private ChristmasTree tree;
public TreeDecorator(ChristmasTree tree) {
this.tree = tree;
}
@Override
public String decorate() {
return tree.decorate();
}
}
2.3 具体装饰器实现
接下来是一些具体的装饰器类,例如灯泡装饰:
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";
}
}
还有一个彩带装饰器(为了完整性补充):
public class Garland extends TreeDecorator {
public Garland(ChristmasTree tree) {
super(tree);
}
public String decorate() {
return super.decorate() + decorateWithGarland();
}
private String decorateWithGarland() {
return " with Garland";
}
}
2.4 使用装饰器
现在我们可以灵活地组合装饰器来生成不同的装饰效果:
@Test
public 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
包装。tree2
则被层层包装:两层Garland
+ 一层BubbleLights
。
这就是装饰器模式的魅力:运行时动态组合行为,而无需预先定义所有可能的组合。
3. 总结
装饰器模式适用于以下几种情况:
✅ 当你需要在运行时动态地给对象添加功能或修改其行为
✅ 当你不想通过继承来扩展类(因为会导致类爆炸)
✅ 当你需要对单个对象进行增强而不影响其他实例
如果你觉得继承太死板,或者想避免大量的子类膨胀,装饰器模式是一个非常实用的选择。
📦 本例完整代码见 GitHub:design-patterns-structural