Appearance
装饰器模式 (Decorator Pattern)
概述
在不改变原有类的前提下,动态地为对象添加功能。
也就是说,用“包装”方式给对象增加功能,而不是修改原类或使用子类继承。
装饰器模式通过“包裹”的方式,为对象动态添加功能,是继承的强力替代方案,也是 Spring AOP、Java IO 等框架广泛应用的核心设计。
适用场景
想增强类的功能,但不希望通过继承(继承会导致子类爆炸);
需要在运行时动态添加/撤销功能;
多个功能可以灵活组合(如 IO 流、文本格式、权限等);
想遵循开闭原则:对扩展开放,对修改关闭。
类图结构
plaintext
┌───────────────┐
│ Component │ ← 抽象组件(定义接口)
└───────┬───────┘
│
┌───────▼─────────┐
│ ConcreteComponent│ ← 具体组件(原始对象)
└───────┬──────────┘
│
┌───────▼────────────┐
│ Decorator │ ← 抽象装饰器,持有组件引用
└───────┬────────────┘
│
┌───────▼───────────────┐
│ ConcreteDecoratorA/B │ ← 具体装饰器,实现增强功能
└────────────────────────┘
核心组件
1. Component(抽象组件)
定义对象的接口,可以给这些对象动态地添加职责。
2. ConcreteComponent(具体组件)
定义一个对象,可以给这个对象添加一些职责。
3. Decorator(抽象装饰器)
维持一个指向Component对象的引用,并定义一个与Component接口一致的接口。
4. ConcreteDecorator(具体装饰器)
向组件添加职责。
实际代码示例
示例1:咖啡店订单系统
java
// 抽象组件:饮品接口
public interface Beverage {
String getDescription();
double getCost();
}
// 具体组件:基础咖啡
public class Espresso implements Beverage {
@Override
public String getDescription() {
return "浓缩咖啡";
}
@Override
public double getCost() {
return 1.99;
}
}
public class HouseBlend implements Beverage {
@Override
public String getDescription() {
return "综合咖啡";
}
@Override
public double getCost() {
return 0.89;
}
}
// 抽象装饰器
public abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
@Override
public abstract String getDescription();
}
// 具体装饰器:牛奶
public class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 牛奶";
}
@Override
public double getCost() {
return beverage.getCost() + 0.10;
}
}
// 具体装饰器:摩卡
public class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 摩卡";
}
@Override
public double getCost() {
return beverage.getCost() + 0.20;
}
}
// 具体装饰器:豆浆
public class Soy extends CondimentDecorator {
public Soy(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 豆浆";
}
@Override
public double getCost() {
return beverage.getCost() + 0.15;
}
}
// 具体装饰器:奶泡
public class Whip extends CondimentDecorator {
public Whip(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", 奶泡";
}
@Override
public double getCost() {
return beverage.getCost() + 0.10;
}
}
// 使用示例
public class CoffeeShop {
public static void main(String[] args) {
// 点一杯浓缩咖啡
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.getCost());
// 点一杯综合咖啡,加双倍摩卡,加奶泡
Beverage beverage2 = new HouseBlend();
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.getCost());
// 点一杯浓缩咖啡,加豆浆,加摩卡,加奶泡
Beverage beverage3 = new Espresso();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription() + " $" + beverage3.getCost());
}
}
示例2:文本处理系统
java
// 抽象组件:文本处理接口
public interface TextProcessor {
String process(String text);
}
// 具体组件:基础文本处理器
public class PlainTextProcessor implements TextProcessor {
@Override
public String process(String text) {
return text;
}
}
// 抽象装饰器
public abstract class TextDecorator implements TextProcessor {
protected TextProcessor processor;
public TextDecorator(TextProcessor processor) {
this.processor = processor;
}
@Override
public String process(String text) {
return processor.process(text);
}
}
// 具体装饰器:加密处理
public class EncryptionDecorator extends TextDecorator {
public EncryptionDecorator(TextProcessor processor) {
super(processor);
}
@Override
public String process(String text) {
String processedText = super.process(text);
return encrypt(processedText);
}
private String encrypt(String text) {
// 简单的加密实现(实际应用中应使用更安全的加密算法)
StringBuilder encrypted = new StringBuilder();
for (char c : text.toCharArray()) {
encrypted.append((char) (c + 1));
}
return "[ENCRYPTED]" + encrypted.toString();
}
}
// 具体装饰器:压缩处理
public class CompressionDecorator extends TextDecorator {
public CompressionDecorator(TextProcessor processor) {
super(processor);
}
@Override
public String process(String text) {
String processedText = super.process(text);
return compress(processedText);
}
private String compress(String text) {
// 简单的压缩实现(移除重复空格)
String compressed = text.replaceAll("\\s+", " ").trim();
return "[COMPRESSED]" + compressed;
}
}
// 具体装饰器:Base64编码
public class Base64Decorator extends TextDecorator {
public Base64Decorator(TextProcessor processor) {
super(processor);
}
@Override
public String process(String text) {
String processedText = super.process(text);
return encodeBase64(processedText);
}
private String encodeBase64(String text) {
// 使用Java 8的Base64编码
return "[BASE64]" + java.util.Base64.getEncoder().encodeToString(text.getBytes());
}
}
// 具体装饰器:日志记录
public class LoggingDecorator extends TextDecorator {
public LoggingDecorator(TextProcessor processor) {
super(processor);
}
@Override
public String process(String text) {
System.out.println("处理文本: " + text.substring(0, Math.min(text.length(), 20)) + "...");
String result = super.process(text);
System.out.println("处理完成,结果长度: " + result.length());
return result;
}
}
// 使用示例
public class TextProcessingDemo {
public static void main(String[] args) {
String originalText = "这是一个需要处理的文本内容,包含多个空格 和特殊字符!";
// 基础处理
TextProcessor processor = new PlainTextProcessor();
System.out.println("原始: " + processor.process(originalText));
// 添加压缩功能
processor = new CompressionDecorator(processor);
System.out.println("压缩: " + processor.process(originalText));
// 添加加密功能
processor = new EncryptionDecorator(processor);
System.out.println("加密: " + processor.process(originalText));
// 添加Base64编码
processor = new Base64Decorator(processor);
System.out.println("Base64: " + processor.process(originalText));
// 添加日志记录
processor = new LoggingDecorator(processor);
System.out.println("\n最终处理结果:");
String finalResult = processor.process(originalText);
System.out.println(finalResult);
}
}
优缺点分析
优点
灵活性高
- 可以在运行时动态添加或移除功能
- 支持多种装饰器的任意组合
- 比继承更加灵活
遵循开闭原则
- 对扩展开放:可以轻松添加新的装饰器
- 对修改关闭:不需要修改现有代码
避免类爆炸
- 不需要为每种功能组合创建子类
- 通过组合而非继承实现功能扩展
单一职责原则
- 每个装饰器只负责一种功能的增强
- 功能职责清晰分离
透明性
- 装饰器和被装饰对象实现相同接口
- 客户端无需知道对象是否被装饰
缺点
复杂性增加
- 多层装饰可能导致调试困难
- 对象创建过程变得复杂
性能开销
- 每个装饰器都会增加一层方法调用
- 多层装饰可能影响性能
装饰顺序敏感
- 不同的装饰顺序可能产生不同的结果
- 需要仔细考虑装饰器的应用顺序
类型识别困难
- 被多层装饰的对象难以进行类型检查
- instanceof操作可能不如预期
与其他模式的对比
装饰器模式 vs 适配器模式
特性 | 装饰器模式 | 适配器模式 |
---|---|---|
目的 | 增强对象功能 | 接口转换 |
接口 | 保持原接口不变 | 转换为新接口 |
功能 | 添加新功能 | 使不兼容接口兼容 |
透明性 | 对客户端透明 | 客户端知道适配过程 |
装饰器模式 vs 代理模式
特性 | 装饰器模式 | 代理模式 |
---|---|---|
目的 | 增强功能 | 控制访问 |
关注点 | 功能扩展 | 访问控制、延迟加载等 |
透明性 | 完全透明 | 可能不透明 |
组合 | 支持多层装饰 | 通常单层代理 |
装饰器模式 vs 策略模式
特性 | 装饰器模式 | 策略模式 |
---|---|---|
目的 | 动态添加功能 | 算法选择 |
结构 | 包装结构 | 组合结构 |
运行时 | 可动态组合 | 可动态切换 |
功能 | 功能叠加 | 功能替换 |
实际应用场景
1. Java I/O流
java
// Java I/O是装饰器模式的经典应用
FileInputStream fis = new FileInputStream("data.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
// 每一层都添加了新的功能:
// FileInputStream: 基础文件读取
// BufferedInputStream: 添加缓冲功能
// DataInputStream: 添加数据类型读取功能
2. Spring AOP
java
// Spring AOP通过装饰器模式实现切面编程
@Service
public class UserService {
@Transactional // 事务装饰器
@Cacheable // 缓存装饰器
@Logged // 日志装饰器
public User getUserById(Long id) {
return userRepository.findById(id);
}
}
3. Web中间件
java
// Express.js风格的中间件
public interface Middleware {
void handle(Request request, Response response, Runnable next);
}
public class AuthenticationMiddleware implements Middleware {
private Middleware next;
public AuthenticationMiddleware(Middleware next) {
this.next = next;
}
@Override
public void handle(Request request, Response response, Runnable nextCallback) {
if (isAuthenticated(request)) {
if (next != null) {
next.handle(request, response, nextCallback);
} else {
nextCallback.run();
}
} else {
response.setStatus(401);
response.setBody("Unauthorized");
}
}
private boolean isAuthenticated(Request request) {
return request.getHeader("Authorization") != null;
}
}
public class LoggingMiddleware implements Middleware {
private Middleware next;
public LoggingMiddleware(Middleware next) {
this.next = next;
}
@Override
public void handle(Request request, Response response, Runnable nextCallback) {
System.out.println("请求: " + request.getPath());
long startTime = System.currentTimeMillis();
if (next != null) {
next.handle(request, response, () -> {
long endTime = System.currentTimeMillis();
System.out.println("响应: " + response.getStatus() + ", 耗时: " + (endTime - startTime) + "ms");
nextCallback.run();
});
} else {
nextCallback.run();
}
}
}
4. GUI组件装饰
java
// GUI组件的装饰器应用
public interface Component {
void draw();
int getWidth();
int getHeight();
}
public class Window implements Component {
private int width, height;
public Window(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public void draw() {
System.out.println("绘制窗口 (" + width + "x" + height + ")");
}
@Override
public int getWidth() { return width; }
@Override
public int getHeight() { return height; }
}
public abstract class ComponentDecorator implements Component {
protected Component component;
public ComponentDecorator(Component component) {
this.component = component;
}
@Override
public void draw() {
component.draw();
}
@Override
public int getWidth() {
return component.getWidth();
}
@Override
public int getHeight() {
return component.getHeight();
}
}
public class BorderDecorator extends ComponentDecorator {
private int borderWidth;
public BorderDecorator(Component component, int borderWidth) {
super(component);
this.borderWidth = borderWidth;
}
@Override
public void draw() {
super.draw();
System.out.println("添加边框 (宽度: " + borderWidth + ")");
}
@Override
public int getWidth() {
return super.getWidth() + 2 * borderWidth;
}
@Override
public int getHeight() {
return super.getHeight() + 2 * borderWidth;
}
}
public class ScrollDecorator extends ComponentDecorator {
public ScrollDecorator(Component component) {
super(component);
}
@Override
public void draw() {
super.draw();
System.out.println("添加滚动条");
}
@Override
public int getWidth() {
return super.getWidth() + 20; // 滚动条宽度
}
}
模式变种和扩展
1. 透明装饰器模式
java
// 透明装饰器:装饰器和组件有相同的接口
public interface Shape {
void draw();
double getArea();
}
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("绘制圆形,半径: " + radius);
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
public abstract class ShapeDecorator implements Shape {
protected Shape shape;
public ShapeDecorator(Shape shape) {
this.shape = shape;
}
@Override
public void draw() {
shape.draw();
}
@Override
public double getArea() {
return shape.getArea();
}
}
public class ColorDecorator extends ShapeDecorator {
private String color;
public ColorDecorator(Shape shape, String color) {
super(shape);
this.color = color;
}
@Override
public void draw() {
super.draw();
System.out.println("添加颜色: " + color);
}
}
2. 半透明装饰器模式
java
// 半透明装饰器:装饰器可能添加新的方法
public interface DataSource {
void writeData(String data);
String readData();
}
public class FileDataSource implements DataSource {
private String filename;
private String data = "";
public FileDataSource(String filename) {
this.filename = filename;
}
@Override
public void writeData(String data) {
this.data = data;
System.out.println("写入文件 " + filename + ": " + data);
}
@Override
public String readData() {
System.out.println("从文件 " + filename + " 读取数据");
return data;
}
}
public abstract class DataSourceDecorator implements DataSource {
protected DataSource dataSource;
public DataSourceDecorator(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public void writeData(String data) {
dataSource.writeData(data);
}
@Override
public String readData() {
return dataSource.readData();
}
}
public class EncryptionDecorator extends DataSourceDecorator {
public EncryptionDecorator(DataSource dataSource) {
super(dataSource);
}
@Override
public void writeData(String data) {
super.writeData(encrypt(data));
}
@Override
public String readData() {
return decrypt(super.readData());
}
// 新增方法:获取加密状态
public boolean isEncrypted() {
return true;
}
// 新增方法:获取加密算法
public String getEncryptionAlgorithm() {
return "AES-256";
}
private String encrypt(String data) {
return "[ENCRYPTED]" + data;
}
private String decrypt(String data) {
return data.replace("[ENCRYPTED]", "");
}
}
3. 函数式装饰器
java
// 使用函数式接口实现装饰器
@FunctionalInterface
public interface Function<T, R> {
R apply(T input);
// 默认方法:组合装饰器
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
return (T t) -> after.apply(apply(t));
}
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
return (V v) -> apply(before.apply(v));
}
}
// 函数式装饰器示例
public class FunctionalDecoratorDemo {
public static void main(String[] args) {
// 基础函数
Function<String, String> base = text -> text.toUpperCase();
// 装饰器函数
Function<String, String> addPrefix = text -> "PREFIX: " + text;
Function<String, String> addSuffix = text -> text + " :SUFFIX";
Function<String, String> addBrackets = text -> "[" + text + "]";
// 组合装饰器
Function<String, String> decorated = base
.andThen(addPrefix)
.andThen(addSuffix)
.andThen(addBrackets);
String result = decorated.apply("hello world");
System.out.println(result); // [PREFIX: HELLO WORLD :SUFFIX]
}
}
最佳实践
1. 装饰器设计原则
java
// 良好的装饰器基类设计
public abstract class BaseDecorator<T> {
protected final T component;
public BaseDecorator(T component) {
if (component == null) {
throw new IllegalArgumentException("Component cannot be null");
}
this.component = component;
}
// 提供获取原始组件的方法
public T getComponent() {
return component;
}
// 提供解包装方法
@SuppressWarnings("unchecked")
public <U> U unwrap(Class<U> type) {
if (type.isInstance(this)) {
return (U) this;
}
if (component instanceof BaseDecorator) {
return ((BaseDecorator<?>) component).unwrap(type);
}
if (type.isInstance(component)) {
return (U) component;
}
return null;
}
// 检查是否包含特定类型的装饰器
public boolean hasDecorator(Class<?> decoratorType) {
return unwrap(decoratorType) != null;
}
}
2. 装饰器工厂
java
// 装饰器工厂,简化装饰器的创建和组合
public class DecoratorFactory {
public static TextProcessor createTextProcessor(String... decorators) {
TextProcessor processor = new PlainTextProcessor();
for (String decorator : decorators) {
processor = createDecorator(decorator, processor);
}
return processor;
}
private static TextProcessor createDecorator(String type, TextProcessor processor) {
switch (type.toLowerCase()) {
case "encryption":
return new EncryptionDecorator(processor);
case "compression":
return new CompressionDecorator(processor);
case "base64":
return new Base64Decorator(processor);
case "logging":
return new LoggingDecorator(processor);
default:
throw new IllegalArgumentException("Unknown decorator type: " + type);
}
}
// 建造者模式结合装饰器
public static class TextProcessorBuilder {
private TextProcessor processor;
public TextProcessorBuilder() {
this.processor = new PlainTextProcessor();
}
public TextProcessorBuilder withEncryption() {
this.processor = new EncryptionDecorator(processor);
return this;
}
public TextProcessorBuilder withCompression() {
this.processor = new CompressionDecorator(processor);
return this;
}
public TextProcessorBuilder withBase64() {
this.processor = new Base64Decorator(processor);
return this;
}
public TextProcessorBuilder withLogging() {
this.processor = new LoggingDecorator(processor);
return this;
}
public TextProcessor build() {
return processor;
}
}
}
// 使用示例
public class DecoratorFactoryDemo {
public static void main(String[] args) {
// 使用工厂方法
TextProcessor processor1 = DecoratorFactory.createTextProcessor(
"compression", "encryption", "base64", "logging"
);
// 使用建造者模式
TextProcessor processor2 = new DecoratorFactory.TextProcessorBuilder()
.withCompression()
.withEncryption()
.withBase64()
.withLogging()
.build();
String text = "Hello, Decorator Pattern!";
System.out.println(processor1.process(text));
System.out.println(processor2.process(text));
}
}
3. 性能优化策略
java
// 缓存装饰器:避免重复计算
public class CachingDecorator extends TextDecorator {
private final Map<String, String> cache = new ConcurrentHashMap<>();
private final int maxCacheSize;
public CachingDecorator(TextProcessor processor, int maxCacheSize) {
super(processor);
this.maxCacheSize = maxCacheSize;
}
@Override
public String process(String text) {
return cache.computeIfAbsent(text, key -> {
if (cache.size() >= maxCacheSize) {
// 简单的LRU策略:清除一半缓存
cache.clear();
}
return super.process(key);
});
}
public void clearCache() {
cache.clear();
}
public int getCacheSize() {
return cache.size();
}
}
// 异步装饰器:提高性能
public class AsyncDecorator extends TextDecorator {
private final ExecutorService executor;
public AsyncDecorator(TextProcessor processor, ExecutorService executor) {
super(processor);
this.executor = executor;
}
public CompletableFuture<String> processAsync(String text) {
return CompletableFuture.supplyAsync(() -> super.process(text), executor);
}
@Override
public String process(String text) {
try {
return processAsync(text).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("异步处理失败", e);
}
}
}
4. 错误处理和监控
java
// 错误处理装饰器
public class ErrorHandlingDecorator extends TextDecorator {
private final ErrorHandler errorHandler;
public ErrorHandlingDecorator(TextProcessor processor, ErrorHandler errorHandler) {
super(processor);
this.errorHandler = errorHandler;
}
@Override
public String process(String text) {
try {
return super.process(text);
} catch (Exception e) {
return errorHandler.handle(text, e);
}
}
@FunctionalInterface
public interface ErrorHandler {
String handle(String originalText, Exception error);
}
}
// 监控装饰器
public class MonitoringDecorator extends TextDecorator {
private final AtomicLong processCount = new AtomicLong(0);
private final AtomicLong totalProcessingTime = new AtomicLong(0);
private final AtomicLong errorCount = new AtomicLong(0);
public MonitoringDecorator(TextProcessor processor) {
super(processor);
}
@Override
public String process(String text) {
long startTime = System.nanoTime();
try {
String result = super.process(text);
processCount.incrementAndGet();
return result;
} catch (Exception e) {
errorCount.incrementAndGet();
throw e;
} finally {
long endTime = System.nanoTime();
totalProcessingTime.addAndGet(endTime - startTime);
}
}
public long getProcessCount() {
return processCount.get();
}
public double getAverageProcessingTime() {
long count = processCount.get();
return count > 0 ? (double) totalProcessingTime.get() / count / 1_000_000 : 0; // 毫秒
}
public long getErrorCount() {
return errorCount.get();
}
public double getErrorRate() {
long total = processCount.get() + errorCount.get();
return total > 0 ? (double) errorCount.get() / total : 0;
}
}
总结
装饰器模式是一种非常实用的结构型设计模式,它通过组合而非继承的方式为对象动态添加功能。这种模式在现代软件开发中有着广泛的应用,从Java的I/O流到Spring的AOP,从Web中间件到GUI组件,都能看到装饰器模式的身影。
核心价值
- 灵活性:运行时动态添加功能,支持任意组合
- 可扩展性:遵循开闭原则,易于添加新功能
- 可维护性:职责分离,每个装饰器专注单一功能
- 透明性:对客户端完全透明,无需修改现有代码
使用建议
- 适度使用:避免过度装饰导致的复杂性
- 注意顺序:装饰器的应用顺序可能影响最终结果
- 性能考虑:多层装饰可能带来性能开销
- 错误处理:提供完善的错误处理机制
- 监控调试:为复杂的装饰器链提供监控和调试支持
装饰器模式是面向对象设计中"组合优于继承"原则的完美体现,它为我们提供了一种优雅的方式来扩展对象功能,是每个开发者都应该掌握的重要设计模式。