概念
动态地为对象添加额外的功能,而不影响原对象
包装而非继承,扩展而非修改
应用场景
对于已经实现基本功能类,出现添加新功能的需求时,使用装饰模式可以在不修改原代码的基础上添加新功能
适合功能经常变动的场景,定义装饰器,客户端按需使用
基本结构

1)组件接口(Component):定义对象的接口,所有的具体组件和装饰器都实现这个接口
2)具体组件(ConcreteComponent):原始对象,定义了核心的功能实现
3)抽象装饰器(Decorator):实现组件接口,内部持有一个被装饰对象
4)具体装饰器(ConcreteDecorator):继承抽象装饰器,负责给组件对象添加新的功能
代码实现
以“文本渲染增强”为例
组件接口
定义所有各类租借共同的接口,保证具体组件和装饰器遵循统一的调用规范
public interface TextComponent {
String render();
}
具体组件
被装饰的核心组件,包含了基本功能,时装饰链的起点
public class PlainText implements TextComponent {
private String content;
public PlainText(String content) {
this.content = content;
}
@Override
public String render() {
return content;
}
}
抽象装饰器
用于包裹基础组件(通过接口作为类型包含一个被装饰对象)并扩展功能
装饰器的通用抽象父类,作为扩展功能的基础,同时继承接口来保持统一的接口
public abstract class TextDecorator implements TextComponent {
protected TextComponent component;
public TextDecorator(TextComponent component) {
this.component = component;
}
}
具体装饰器
继承抽象装饰器,重写接口方法实现扩展功能
public class BoldDecorator extends TextDecorator {
public BoldDecorator(TextComponent component) {
super(component);
}
@Override
public String render() {
return "<b>" + component.render() + "</b>";
}
}
public class ColorDecorator extends TextDecorator {
private String color;
public ColorDecorator(TextComponent component, String color) {
super(component);
this.color = color;
}
@Override
public String render() {
return "<span style='color:" + color + "'>" + component.render() + "</span>";
}
}
客户端调用
按需组合装饰器,动态增强文本
public class Client {
public static void main(String[] args) {
TextComponent text = new PlainText("Hello, Decorator!");
// 添加加粗
text = new BoldDecorator(text);
// 添加红色字体
text = new ColorDecorator(text, "red");
System.out.println("最终渲染结果:");
System.out.println(text.render());
}
}
优缺点
优点
1)扩展功能更灵活:允许你在不修改原始类代码的前提下,动态地给对象增加额外的功能
2)避免类过多:如果用继承来应对各种功能组合,很容易导致子类数量成倍增加,维护压力大
3)可以组合使用:多个装饰类可以灵活叠加,按需组合功能
缺点
1)调试复杂:装饰模式是通过一层一层地包装对象,不易调试
2)影响性能:如果装饰链太长,每次调用方法都要经过多层对象转发,虽然每层逻辑可能都很轻,但叠加起来也可能对性能有些影响
