// 1. 기본 컴포넌트 (인터페이스)
interface Coffee {
    String getDescription();
    double getCost();
}

// 2. 기본 커피 클래스
class BasicCoffee implements Coffee {
    public String getDescription() {
        return "기본 커피";
    }

    public double getCost() {
        return 3000;
    }
}

// 3. 데코레이터 (추상 클래스)
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

    public double getCost() {
        return decoratedCoffee.getCost();
    }
}

// 4. 추가 기능: 우유 추가
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return super.getDescription() + ", 우유 추가";
    }

    public double getCost() {
        return super.getCost() + 500;
    }
}

// 5. 추가 기능: 시럽 추가
class SyrupDecorator extends CoffeeDecorator {
    public SyrupDecorator(Coffee coffee) {
        super(coffee);
    }

    public String getDescription() {
        return super.getDescription() + ", 시럽 추가";
    }

    public double getCost() {
        return super.getCost() + 300;
    }
}

// 6. 사용 예
public class Main {
    public static void main(String[] args) {
        Coffee coffee = new BasicCoffee(); // 기본 커피
        coffee = new MilkDecorator(coffee); // 우유 추가
        coffee = new SyrupDecorator(coffee); // 시럽 추가

        System.out.println(coffee.getDescription() + " 가격: " + coffee.getCost() + "원");
    }
}

✅ 장점 • 기존 코드를 수정하지 않고 기능 확장 가능 (OCP 준수) • 객체 간 조합을 통해 다양한 기능을 동적으로 추가 가능 • 상속보다 유연한 설계 가능

❌ 단점 • 데코레이터가 많아지면 구조가 복잡해질 수 있음 • 객체가 여러 개 감싸지는 방식이라 디버깅이 어려울 수 있음