本文目录导读:

装饰器模式核心思想
装饰器模式允许动态地给对象添加额外功能,比继承更灵活,核心是:
- 不修改原有类结构
- 通过组合方式扩展功能
- 支持多层装饰
基础案例:咖啡点单系统
抽象组件接口
// 咖啡组件接口
public interface Coffee {
String getDescription();
double cost();
}
具体组件(基础实现)
// 基础咖啡 - 美式咖啡
public class AmericanCoffee implements Coffee {
@Override
public String getDescription() {
return "美式咖啡";
}
@Override
public double cost() {
return 20.0;
}
}
// 基础咖啡 - 拿铁
public class Latte implements Coffee {
@Override
public String getDescription() {
return "拿铁";
}
@Override
public double cost() {
return 25.0;
}
}
抽象装饰器
// 装饰器抽象类,核心:持有Coffee引用
public abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
// 默认委托给被装饰对象
@Override
public String getDescription() {
return coffee.getDescription();
}
@Override
public double cost() {
return coffee.cost();
}
}
具体装饰器(功能扩展)
// 加奶装饰器
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " + 牛奶";
}
@Override
public double cost() {
return coffee.cost() + 5.0; // 加奶额外5元
}
}
// 加糖装饰器
public class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " + 糖";
}
@Override
public double cost() {
return coffee.cost() + 2.0; // 加糖额外2元
}
}
// 加奶油装饰器
public class WhipDecorator extends CoffeeDecorator {
public WhipDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " + 奶油";
}
@Override
public double cost() {
return coffee.cost() + 8.0; // 加奶油额外8元
}
}
使用示例
基本使用
public class CoffeeShop {
public static void main(String[] args) {
// 基础美式咖啡
Coffee coffee = new AmericanCoffee();
System.out.println(coffee.getDescription() + ":¥" + coffee.cost());
// 输出:美式咖啡:¥20.0
// 美式 + 牛奶
Coffee milkCoffee = new MilkDecorator(new AmericanCoffee());
System.out.println(milkCoffee.getDescription() + ":¥" + milkCoffee.cost());
// 输出:美式咖啡 + 牛奶:¥25.0
// 美式 + 牛奶 + 糖
Coffee sweetMilkCoffee = new SugarDecorator(
new MilkDecorator(new AmericanCoffee())
);
System.out.println(sweetMilkCoffee.getDescription() + ":¥" + sweetMilkCoffee.cost());
// 输出:美式咖啡 + 牛奶 + 糖:¥27.0
// 拿铁 + 奶油 + 糖
Coffee latteWithWhipAndSugar = new SugarDecorator(
new WhipDecorator(new Latte())
);
System.out.println(latteWithWhipAndSugar.getDescription() + ":¥" + latteWithWhipAndSugar.cost());
// 输出:拿铁 + 奶油 + 糖:¥35.0
}
}
动态组合
// 可以根据用户选择动态组合
public Coffee createCustomCoffee(String base, List<String> addons) {
Coffee coffee;
// 选择基底
switch (base) {
case "美式":
coffee = new AmericanCoffee();
break;
case "拿铁":
coffee = new Latte();
break;
default:
throw new IllegalArgumentException("未知咖啡类型");
}
// 动态添加配料
for (String addon : addons) {
switch (addon) {
case "牛奶":
coffee = new MilkDecorator(coffee);
break;
case "糖":
coffee = new SugarDecorator(coffee);
break;
case "奶油":
coffee = new WhipDecorator(coffee);
break;
}
}
return coffee;
}
更复杂的功能拓展
添加新功能:杯子大小
// 杯子大小装饰器
public class SizeDecorator extends CoffeeDecorator {
private String size;
public SizeDecorator(Coffee coffee, String size) {
super(coffee);
this.size = size;
}
@Override
public String getDescription() {
return size + "杯 " + coffee.getDescription();
}
@Override
public double cost() {
double baseCost = coffee.cost();
switch (size) {
case "大":
return baseCost + 5.0;
case "中":
return baseCost + 3.0;
default: // 小
return baseCost;
}
}
}
// 使用
Coffee largeMilkCoffee = new SizeDecorator(
new MilkDecorator(new AmericanCoffee()), "大"
);
System.out.println(largeMilkCoffee.getDescription() + ":¥" + largeMilkCoffee.cost());
// 输出:大杯 美式咖啡 + 牛奶:¥30.0
添加新功能:温度控制
public class TemperatureDecorator extends CoffeeDecorator {
private String temperature;
public TemperatureDecorator(Coffee coffee, String temperature) {
super(coffee);
this.temperature = temperature;
}
@Override
public String getDescription() {
return coffee.getDescription() + "(" + temperature + ")";
}
@Override
public double cost() {
// 冰咖啡额外收费
if ("冰".equals(temperature)) {
return coffee.cost() + 2.0;
}
return coffee.cost();
}
}
// 多层装饰示例
Coffee customCoffee = new TemperatureDecorator(
new SizeDecorator(
new SugarDecorator(
new WhipDecorator(new Latte())
), "中"
), "冰"
);
System.out.println(customCoffee.getDescription() + ":¥" + customCoffee.cost());
// 输出:中杯 拿铁 + 奶油 + 糖(冰):¥40.0
进阶:使用接口+泛型
// 更通用的装饰器接口
public interface Decorator<T> {
T decorate(T target);
}
// 具体装饰器可以更灵活
public class LoggingDecorator<T> implements Decorator<T> {
@Override
public T decorate(T target) {
// 可以为任何对象添加日志功能
System.out.println("调用对象:" + target.getClass().getSimpleName());
return target;
}
}
实际应用场景
- Java I/O流:
BufferedInputStream装饰FileInputStream - Spring框架:
@Transactional、@Cacheable等注解 - Servlet Filter:多个Filter链式处理请求
- 日志框架:不同Appender、Layout的组合
注意事项
优点
- ✅ 比继承更灵活
- ✅ 遵循开闭原则
- ✅ 功能可以动态组合
- ✅ 避免类爆炸
缺点
- ❌ 会产生很多小类
- ❌ 多层装饰时调试复杂
- ❌ 装饰顺序可能影响结果
最佳实践
- 明确边界:装饰器应只添加功能,不改变核心逻辑
- 保持简单:避免超过3-4层装饰
- 工厂方法:结合工厂模式简化创建过程
- 文档清晰:记录装饰器的执行顺序
通过装饰器模式,您可以像搭积木一样灵活组合功能,既保持了代码的整洁,又提供了无限扩展的可能性。