介绍Java装饰模式
介绍Java装饰模式
装饰模式用于给对象动态或静态地附加额外的责任。装饰器给原对象提供了额外功能接口。
实现该模式,我们更倾向于使用组合而不是继承,因为可以减少每个装饰元素子类化的开销。递归调用该模式可以根据需要对原对象进行多次装饰。
示例说明
假设我们有一个圣诞树对象需要装饰,装饰不能改变原对象,仅给对象增加额外功能。我们打算增加一些如花环(garland)、金属丝(tinsel)、树顶(treetop)、泡泡灯(bubble light)等:
该实现过程我们遵循GOF设计和命名规范,首先创建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;
public TreeDecorator(ChristmasTree tree) {
this.tree = tree;
}
@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";
}
}
其他的装饰元素一样:
public class Garland extends TreeDecorator {
public Garland(ChristmasTree tree) {
super(tree);
}
public String decorate() {
return super.decorate() + decorateWithGarland();
}
private String decorateWithGarland() {
return " with Garland";
}
}
下面测试结果为True:
@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对象装饰一个BubbleLights 和两个Garlands。该模式让我们可以灵活地在运行时根据需要增加装饰元素。
总结
本文,我们探讨了装饰模式。一般用于下列场景:
- 一般用于增加、增强,甚至删除对象行为或状态。
- 只想修改类的单个对象的功能而不改变其他对象。