#include <iostream>
#include <memory>
#include <string>
class Beverage {
public:
virtual ~Beverage() = default;
virtual std::string getDescription() const = 0;
virtual double cost() const = 0;
};
class Espresso : public Beverage {
public:
std::string getDescription() const override {
return "Espresso";
}
double cost() const override {
return 1.99;
}
};
class HouseBlend : public Beverage {
public:
std::string getDescription() const override {
return "House Blend Coffee";
}
double cost() const override {
return 0.89;
}
};
class CondimentDecorator : public Beverage {
protected:
std::unique_ptr<Beverage> beverage;
public:
explicit CondimentDecorator(std::unique_ptr<Beverage> b)
: beverage(std::move(b)) {}
};
class Milk : public CondimentDecorator {
public:
explicit Milk(std::unique_ptr<Beverage> b)
: CondimentDecorator(std::move(b)) {}
std::string getDescription() const override {
return beverage->getDescription() + ", Milk";
}
double cost() const override {
return beverage->cost() + 0.10;
}
};
class Mocha : public CondimentDecorator {
public:
explicit Mocha(std::unique_ptr<Beverage> b)
: CondimentDecorator(std::move(b)) {}
std::string getDescription() const override {
return beverage->getDescription() + ", Mocha";
}
double cost() const override {
return beverage->cost() + 0.20;
}
};
class Soy : public CondimentDecorator {
public:
explicit Soy(std::unique_ptr<Beverage> b)
: CondimentDecorator(std::move(b)) {}
std::string getDescription() const override {
return beverage->getDescription() + ", Soy";
}
double cost() const override {
return beverage->cost() + 0.15;
}
};
void printBeverage(const Beverage& beverage) {
std::cout << beverage.getDescription()
<< " $" << beverage.cost() << std::endl;
}
int main() {
auto espresso = std::make_unique<Espresso>();
printBeverage(*espresso);
auto houseBlend = std::make_unique<HouseBlend>();
auto drink = std::make_unique<Mocha>(
std::make_unique<Mocha>(
std::make_unique<Milk>(std::move(houseBlend))
)
);
printBeverage(*drink);
auto espresso2 = std::make_unique<Espresso>();
auto drink2 = std::make_unique<Soy>(
std::make_unique<Mocha>(std::move(espresso2))
);
printBeverage(*drink2);
return 0;
}