装饰器模式通过“所有组件与装饰器实现同一接口”维持接口一致性,客户端仅依赖接口编程;装饰器组合被装饰对象并委托调用,在不改变方法签名前提下增强行为,支持无限嵌套。

装饰器模式中,接口一致性靠“装饰类实现同一接口”来维持——所有具体组件和装饰器都实现同一个接口,客户端只依赖接口编程,不关心具体是原始对象还是被层层包装的对象。
接口是装饰器模式的契约核心
装饰器模式要求目标类(被装饰者)和所有装饰类(如 LoggingDecorator、CachingDecorator)共同实现一个统一的接口(例如 DataSource)。这个接口定义了对外暴露的行为契约,比如:
public interface DataSource {
void write(String data);
String read();
}
只要遵循该接口,无论底层是 FileDataSource、EncryptedDataSource 还是 CompressedDataSource,调用方都可无差别使用 write() 和 read() 方法。
装饰器自身必须实现相同接口并持有被装饰对象
每个装饰器不是继承,而是组合:它持有一个 DataSource 类型的引用,并在自己实现的方法中调用该引用的方法(可能前置/后置增强逻辑):
public class LoggingDecorator implements DataSource {
private final DataSource delegate;
public LoggingDecorator(DataSource delegate) {
this.delegate = delegate;
}
@Override
public void write(String data) {
System.out.println("Logging: writing " + data);
delegate.write(data); // 委托给被装饰对象
}
@Override
public String read() {
String result = delegate.read();
System.out.println("Logging: read " + result);
return result;
}
}
- 构造时传入
DataSource,保证组合关系灵活(可装饰任意实现了该接口的对象) - 所有方法签名与接口完全一致,不新增、不删减、不改形参/返回类型
- 行为增强通过“调用前/后加逻辑 + 委托执行”完成,而非重写接口定义
支持多层装饰的关键:类型兼容性
因为所有装饰器都实现 DataSource,所以可以无限嵌套:
DataSource source = new FileDataSource();
source = new LoggingDecorator(source);
source = new CachingDecorator(source);
source = new EncryptedDecorator(source);
source.write("hello"); // 仍调用 write(),行为由整条链协同完成
每层装饰器看到的都是 DataSource 类型,编译期和运行期类型始终一致。JVM 不关心它是原始实现还是某层装饰器——只要它实现了接口,就能作为参数传入、作为返回值传出、被统一调用。
避免破坏一致性的常见错误
- 装饰器未实现接口,仅继承某个具体类 → 失去多态能力,无法替代原对象
-
装饰器添加了新方法(如
enableCache()) → 客户端若依赖该方法,就无法再用纯接口变量接收,违背“面向接口编程”原则 -
装饰器改变了方法签名(如让
read()抛出新异常) → 违反里氏替换原则,调用方需额外处理,接口契约被破坏 - 用抽象类代替接口定义装饰结构 → 虽可行,但限制了被装饰类必须继承该抽象类,丧失组合灵活性;接口更轻量、更符合装饰器初衷
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











