本文介绍如何通过装饰器模式(decorator pattern)在无法修改现有子类(如 cow、pig)的情况下,为 animal 继承体系注入统一的扩展逻辑(如自定义 die()、droploot()),实现“运行时组合式增强”,兼顾类型安全与开闭原则。
本文介绍如何通过装饰器模式(decorator pattern)在无法修改现有子类(如 cow、pig)的情况下,为 animal 继承体系注入统一的扩展逻辑(如自定义 die()、droploot()),实现“运行时组合式增强”,兼顾类型安全与开闭原则。
在面向对象设计中,当面临“需为多个已有子类统一增强某些行为,但又严禁修改其源码”这一典型约束时,传统继承(extends)和泛型类继承(如 class Pet
装饰器模式的核心思想是:让新类既“是”目标类型(通过继承抽象基类),又“拥有”目标实例(通过组合),从而在保持接口一致性的同时,灵活控制方法调用流程。它不是在编译期硬编码继承关系,而是在运行时动态包装对象,实现关注点分离。
以下为完整实现示例(基于您提供的 Animal 体系):
// 抽象基类 —— 定义契约
public abstract class Animal {
public abstract void eat();
public abstract void ai();
public abstract void die();
public abstract void dropLoot();
}
// 不可修改的已有子类(Cow)
public class Cow extends Animal {
@Override
public void eat() { System.out.println("Cow eats grass"); }
@Override
public void ai() { System.out.println("Cow performs grazing AI"); }
@Override
public void die() { System.out.println("Cow collapses"); }
@Override
public void dropLoot() { System.out.println("Cow drops leather and beef"); }
public void moo() { System.out.println("Moo!"); } // 扩展方法,仅 Cow 可见
}
// 同样不可修改的 Pig 类(略,结构同 Cow)
public class Pig extends Animal {
@Override public void eat() { System.out.println("Pig eats slop"); }
@Override public void ai() { System.out.println("Pig performs rooting AI"); }
@Override public void die() { System.out.println("Pig falls silent"); }
@Override public void dropLoot() { System.out.println("Pig drops pork and hide"); }
}
// ✅ 关键:Pet 装饰器 —— 继承 Animal,组合具体 Animal 实例
public class Pet extends Animal {
private final Animal decorated; // 组合:持有被装饰对象
public Pet(Animal animal) {
this.decorated = Objects.requireNonNull(animal, "Animal cannot be null");
}
// 对于无需增强的方法:直接委托(delegation)
@Override
public void eat() { decorated.eat(); }
@Override
public void ai() { decorated.ai(); }
// 对于需统一增强的方法:前置/后置逻辑 + 委托调用
@Override
public void die() {
System.out.println("[Pet] Performing last rites...");
decorated.die(); // 调用原始子类逻辑(Cow.die 或 Pig.die)
System.out.println("[Pet] Pet spirit ascends.");
}
// 对于需完全重写的行为:不调用 decorated,提供全新实现
@Override
public void dropLoot() {
System.out.println("[Pet] Dropping affectionate loot: 1x Pet Bond Token");
// 注意:此处完全替代 Cow/Pig 的 dropLoot,不调用 decorated.dropLoot()
}
}使用方式简洁直观:
立即学习“Java免费学习笔记(深入)”;
public class Main {
public static void main(String[] args) {
Animal cow = new Cow();
Animal pig = new Pig();
// 动态包装:为任意 Animal 子类实例赋予 Pet 行为
Animal petCow = new Pet(cow);
Animal petPig = new Pet(pig);
// 所有调用均符合 Animal 接口,客户端无感知底层是装饰还是原生
petCow.ai(); // → "Cow performs grazing AI" (委托)
petPig.ai(); // → "Pig performs rooting AI" (委托)
petCow.die(); // → "[Pet] Performing last rites..." → "Cow collapses" → "[Pet] Pet spirit ascends."
petPig.die(); // → 同理,但触发 Pig.die()
petCow.dropLoot(); // → "[Pet] Dropping affectionate loot: 1x Pet Bond Token" (完全重写)
petPig.dropLoot(); // → 同上,统一行为
}
}关键优势与注意事项:
- ✅ 零侵入性:Cow、Pig 类源码无需任何改动,完美满足约束;
- ✅ 高复用性:一个 Pet 类即可装饰任意 Animal 子类(未来新增 Sheep 也适用);
- ✅ 类型安全:Pet 是 Animal 的合法子类型,可无缝用于所有接受 Animal 的上下文(多态);
- ⚠️ 不可访问子类特有方法:Pet 只能覆盖 Animal 中声明的方法(如 moo() 无法被 Pet 直接调用或重写),这恰是封装性的体现;
- ⚠️ 注意空指针与生命周期:decorated 字段应设为 final 并校验非空,避免运行时异常;若被装饰对象状态可变,需确保线程安全;
- ? 可叠加装饰:如需更多层行为(如 TamedPet extends Pet),可继续套用相同模式,形成装饰链。
综上,装饰器模式以组合替代继承,在受限条件下实现了高度灵活、可维护且符合开闭原则的代码增强方案——它不改变旧世界,却为新需求构建了清晰、可控的扩展边界。


















