Java装饰器模式实现详解
装饰器模式允许我们动态地给一个对象添加新的行为,而无需修改其原有类结构,下面通过咖啡店系统的案例来说明。

基础结构设计
// 1. 抽象组件 - 饮料接口
interface Beverage {
String getDescription();
double cost();
}
// 2. 具体组件 - 基础咖啡
class Espresso implements Beverage {
@Override
public String getDescription() {
return "浓缩咖啡";
}
@Override
public double cost() {
return 15.0;
}
}
class HouseBlend implements Beverage {
@Override
public String getDescription() {
return "综合咖啡";
}
@Override
public double cost() {
return 12.0;
}
}
class DarkRoast implements Beverage {
@Override
public String getDescription() {
return "深度烘焙咖啡";
}
@Override
public double cost() {
return 18.0;
}
}
装饰器基类
// 3. 抽象装饰器
abstract class CondimentDecorator implements Beverage {
protected Beverage beverage;
public CondimentDecorator(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription();
}
@Override
public double cost() {
return beverage.cost();
}
}
具体装饰器实现
// 4. 具体装饰器 - 配料
class Milk extends CondimentDecorator {
public Milk(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 牛奶";
}
@Override
public double cost() {
return beverage.cost() + 3.0;
}
}
class Mocha extends CondimentDecorator {
public Mocha(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 摩卡";
}
@Override
public double cost() {
return beverage.cost() + 5.0;
}
}
class Whip extends CondimentDecorator {
public Whip(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 奶油";
}
@Override
public double cost() {
return beverage.cost() + 4.0;
}
}
class Soy extends CondimentDecorator {
public Soy(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + " + 豆浆";
}
@Override
public double cost() {
return beverage.cost() + 2.0;
}
}
客户端使用示例
public class CoffeeShop {
public static void main(String[] args) {
// 基础咖啡
Beverage espresso = new Espresso();
System.out.println(espresso.getDescription() + " 价格: ¥" + espresso.cost());
// 添加配料
Beverage latte = new Milk(espresso);
System.out.println(latte.getDescription() + " 价格: ¥" + latte.cost());
// 多层装饰
Beverage mochaLatte = new Mocha(latte);
System.out.println(mochaLatte.getDescription() + " 价格: ¥" + mochaLatte.cost());
// 复杂组合
Beverage custom = new Whip(new Mocha(new Soy(new DarkRoast())));
System.out.println(custom.getDescription() + " 价格: ¥" + custom.cost());
// 动态添加额外配料
Beverage doubleMochaLatte = new Mocha(new Mocha(new Milk(new HouseBlend())));
System.out.println(doubleMochaLatte.getDescription() + " 价格: ¥" + doubleMochaLatte.cost());
}
}
输出结果
浓缩咖啡 价格: ¥15.0
浓缩咖啡 + 牛奶 价格: ¥18.0
浓缩咖啡 + 牛奶 + 摩卡 价格: ¥23.0
深度烘焙咖啡 + 豆浆 + 摩卡 + 奶油 价格: ¥29.0
综合咖啡 + 牛奶 + 摩卡 + 摩卡 价格: ¥25.0
改进版本 - 使用泛型
// 更通用的装饰器实现
abstract class AbstractDecorator<T extends Beverage> implements Beverage {
protected T component;
public AbstractDecorator(T component) {
this.component = component;
}
@Override
public String getDescription() {
return component.getDescription();
}
@Override
public double cost() {
return component.cost();
}
}
// 使用泛型的具体装饰器
class Sugar<T extends Beverage> extends AbstractDecorator<T> {
public Sugar(T component) {
super(component);
}
@Override
public String getDescription() {
return super.getDescription() + " + 糖";
}
@Override
public double cost() {
return super.cost() + 1.0;
}
}
装饰器模式的优势
- 开闭原则:无需修改现有类即可扩展功能
- 灵活性:可以在运行时动态组合不同的行为
- 避免类膨胀:避免了创建大量子类
- 细粒度控制:可以精确控制添加的功能
实际应用场景
- Java I/O流:
BufferedReader装饰FileReader - GUI组件:添加滚动条、边框等功能
- 日志系统:添加时间戳、格式化等功能
- 权限控制:动态添加访问控制功能
这个案例展示了装饰器模式的核心思想:通过组合而不是继承来扩展对象的功能,既保持了类的单一职责,又提供了极大的灵活性。