Java装饰者模式案例

wen java案例 2

本文目录导读:

Java装饰者模式案例

  1. 基本结构
  2. 客户端测试代码
  3. 运行结果
  4. 进阶版:带容量大小的咖啡
  5. 装饰者模式的优势
  6. 适用场景

我将为您提供一个完整的Java装饰者模式案例,以咖啡店点餐系统为例来演示。

基本结构

// 1. 抽象组件(Component)- 饮料接口
public interface Beverage {
    String getDescription();
    double cost();
}
// 2. 具体组件(ConcreteComponent)- 具体的饮料
public class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return "浓缩咖啡";
    }
    @Override
    public double cost() {
        return 15.0;
    }
}
public class HouseBlend implements Beverage {
    @Override
    public String getDescription() {
        return "综合咖啡";
    }
    @Override
    public double cost() {
        return 12.0;
    }
}
public class Decaf implements Beverage {
    @Override
    public String getDescription() {
        return "低因咖啡";
    }
    @Override
    public double cost() {
        return 13.0;
    }
}
// 3. 抽象装饰者(Decorator)- 调料装饰器
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
    @Override
    public abstract String getDescription();
}
// 4. 具体装饰者(ConcreteDecorator)- 各种调料
public 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;
    }
}
public 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;
    }
}
public 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;
    }
}
public class Soy extends CondimentDecorator {
    public Soy(Beverage beverage) {
        super(beverage);
    }
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", 加豆浆";
    }
    @Override
    public double cost() {
        return beverage.cost() + 4.5;
    }
}

客户端测试代码

public class CoffeeShop {
    public static void main(String[] args) {
        System.out.println("=== 咖啡店点餐系统 ===\n");
        // 1. 点一杯纯浓缩咖啡
        Beverage espresso = new Espresso();
        System.out.println("订单1: " + espresso.getDescription());
        System.out.println("价格: $" + espresso.cost() + "\n");
        // 2. 点一杯综合咖啡,加双份摩卡和牛奶
        Beverage houseBlend = new HouseBlend();
        houseBlend = new Mocha(houseBlend);
        houseBlend = new Mocha(houseBlend);  // 双份摩卡
        houseBlend = new Milk(houseBlend);
        System.out.println("订单2: " + houseBlend.getDescription());
        System.out.println("价格: $" + houseBlend.cost() + "\n");
        // 3. 点一杯低因咖啡,加豆浆和奶泡
        Beverage decaf = new Decaf();
        decaf = new Soy(decaf);
        decaf = new Whip(decaf);
        System.out.println("订单3: " + decaf.getDescription());
        System.out.println("价格: $" + decaf.cost() + "\n");
        // 4. 一份豪华套餐:浓缩咖啡加所有调料
        Beverage deluxe = new Espresso();
        deluxe = new Milk(deluxe);
        deluxe = new Mocha(deluxe);
        deluxe = new Whip(deluxe);
        deluxe = new Soy(deluxe);
        System.out.println("订单4: " + deluxe.getDescription());
        System.out.println("价格: $" + deluxe.cost());
    }
}

运行结果

=== 咖啡店点餐系统 ===
订单1: 浓缩咖啡
价格: $15.0
订单2: 综合咖啡, 加摩卡, 加摩卡, 加牛奶
价格: $25.0
订单3: 低因咖啡, 加豆浆, 加奶泡
价格: $21.5
订单4: 浓缩咖啡, 加牛奶, 加摩卡, 加奶泡, 加豆浆
价格: $31.5

进阶版:带容量大小的咖啡

// 增加容量选项
public enum Size {
    TALL,      // 小杯
    GRANDE,    // 中杯  
    VENTI      // 大杯
}
// 修改抽象组件接口
public interface Beverage {
    String getDescription();
    double cost();
    Size getSize();
    void setSize(Size size);
}
// 重写具体组件
public class Espresso implements Beverage {
    private Size size = Size.GRANDE;
    @Override
    public String getDescription() {
        return "浓缩咖啡";
    }
    @Override
    public double cost() {
        // 根据容量计算价格
        switch(size) {
            case TALL: return 15.0;
            case GRANDE: return 18.0;
            case VENTI: return 21.0;
            default: return 15.0;
        }
    }
    @Override
    public Size getSize() {
        return size;
    }
    @Override
    public void setSize(Size size) {
        this.size = size;
    }
}
// 重写装饰者,根据容量计算调料价格
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;
    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
    @Override
    public Size getSize() {
        return beverage.getSize();
    }
    @Override
    public void setSize(Size size) {
        beverage.setSize(size);
    }
}
public class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        super(beverage);
    }
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", 加摩卡";
    }
    @Override
    public double cost() {
        // 摩卡根据不同容量加价
        double mochaCost = 5.0;
        if (getSize() == Size.TALL) {
            mochaCost = 4.0;
        } else if (getSize() == Size.VENTI) {
            mochaCost = 6.0;
        }
        return beverage.cost() + mochaCost;
    }
}

装饰者模式的优势

优点:

  1. 组合优于继承:动态地添加职责,比继承更灵活
  2. 开闭原则:可以在不修改原有代码的情况下添加新功能
  3. 可选组合:可以自由组合,产生丰富的效果

缺点:

  1. 增加复杂度:会产生很多小类,增加理解难度
  2. 调试困难:多层包装使调试变得复杂
  3. 顺序依赖:某些场景下装饰顺序可能影响最终结果

适用场景

  • 需要动态、透明地给单个对象添加职责
  • 需要扩展一个类的功能,或给一个类增加附加责任
  • 需要动态撤销或恢复对象的某些功能

这个案例完整展示了Java装饰者模式的核心概念:通过包装对象来动态添加功能,而不是通过继承来静态地增加功能。

抱歉,评论功能暂时关闭!