装饰器(Decorator)模式,是一种在运行期动态给某个对象的实例增加功能的方法。
1.图示:
IO源码应用:
// 创建原始的数据源:
InputStream fis = new FileInputStream("test.gz");
// 增加缓冲功能:
InputStream bis = new BufferedInputStream(fis);
// 增加解压缩功能:
InputStream gis = new GZIPInputStream(bis);
Component是接口,对应到IO的就是InputStream这个抽象类;
ComponentA、ComponentB是实际的子类,对应到IO的就是FileInputStream、ServletInputStream这些数据源;
Decorator是用于实现各个附加功能的抽象装饰器,对应到IO的就是FilterInputStream;
从Decorator派生的就是一个一个的装饰器,它们每个都有独立的功能,对应到IO的就是BufferedInputStream、GZIPInputStream等。
2.代码示例
假设我们需要渲染一个HTML的文本,但是文本还可以附加一些效果,比如加粗、变斜体、加下划线等。为了实现动态附加效果,可以采用Decorator模式。
- 顶层接口TextNode
public interface TextNode {
// 设置text:
void setText(String text);
// 获取text:
String getText();
}
- 核心节点,例如
<span>
,它需要从TextNode直接继承
public class SpanNode implements TextNode {
private String text;
public void setText(String text) {
this.text = text;
}
public String getText() {
return "<span>" + text + "</span>";
}
}
- 抽象的Decorator类
public abstract class NodeDecorator implements TextNode {
protected final TextNode target;
protected NodeDecorator(TextNode target) {
this.target = target;
}
public void setText(String text) {
this.target.setText(text);
}
}
- Decorator实现类,增加功能加粗功能
</b>
public class BoldDecorator extends NodeDecorator {
public BoldDecorator(TextNode target) {
super(target);
}
public String getText() {
return "<b>" + target.getText() + "</b>";
}
}
- 调用
可以继续加ItalicDecorator、UnderlineDecorator等。客户端可以自由组合这些Decorator:
TextNode n1 = new SpanNode();
TextNode n2 = new BoldDecorator(new UnderlineDecorator(new SpanNode()));
TextNode n3 = new ItalicDecorator(new BoldDecorator(new SpanNode()));
n1.setText("Hello");
n2.setText("Decorated");
n3.setText("World");
System.out.println(n1.getText());
// 输出<span>Hello</span>
System.out.println(n2.getText());
// 输出<b><u><span>Decorated</span></u></b>
System.out.println(n3.getText());
// 输出<i><b><span>World</span></b></i>