装饰设计模式适用于以下情况:
• 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责;
下面是一个装饰模式的示例程序:
cpp
#include <iostream>
#include <string>
#include <memory>
// Step 1: The Component Interface
class Coffee {
public:
virtual ~Coffee() = default;
virtual std::string getDescription() const = 0;
virtual double getCost() const = 0;
};
// Step 2: Concrete Component (The plain object we want to decorate)
class SimpleCoffee : public Coffee {
public:
std::string getDescription() const override {
return "Simple Coffee";
}
double getCost() const override {
return 2.00; // Base price $2.00
}
};
// Step 3: The Base Decorator
// It maintains a pointer to a wrapped Coffee object and matches its interface
class CoffeeDecorator : public Coffee {
protected:
std::unique_ptr<Coffee> wrappedCoffee_;
public:
CoffeeDecorator(std::unique_ptr<Coffee> coffee) : wrappedCoffee_(std::move(coffee)) {}
std::string getDescription() const override {
return wrappedCoffee_->getDescription();
}
double getCost() const override {
return wrappedCoffee_->getCost();
}
};
// Step 4: Concrete Decorator A (Adds Milk)
class MilkDecorator : public CoffeeDecorator {
public:
MilkDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
std::string getDescription() const override {
// Delegate to the wrapped object, then add milk description
return CoffeeDecorator::getDescription() + ", Milk";
}
double getCost() const override {
// Delegate to the wrapped object, then add milk cost
return CoffeeDecorator::getCost() + 0.50;
}
};
// Step 5: Concrete Decorator B (Adds Sugar)
class SugarDecorator : public CoffeeDecorator {
public:
SugarDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
std::string getDescription() const override {
return CoffeeDecorator::getDescription() + ", Sugar";
}
double getCost() const override {
return CoffeeDecorator::getCost() + 0.25;
}
};
// Client Code
int main() {
std::cout << "--- Ordering Custom Coffees ---\n";
// 1. Order a completely plain coffee
std::unique_ptr<Coffee> myCoffee = std::make_unique<SimpleCoffee>();
std::cout << myCoffee->getDescription() << " costs: $" << myCoffee->getCost() << "\n";
// 2. Wrap it with Milk at runtime
myCoffee = std::make_unique<MilkDecorator>(std::move(myCoffee));
std::cout << myCoffee->getDescription() << " costs: $" << myCoffee->getCost() << "\n";
// 3. Wrap it with Sugar as well
myCoffee = std::make_unique<SugarDecorator>(std::move(myCoffee));
std::cout << myCoffee->getDescription() << " costs: $" << myCoffee->getCost() << "\n";
// 4. Create a pre-configured double-milk coffee from scratch
std::unique_ptr<Coffee> premiumCoffee = std::make_unique<SugarDecorator>(
std::make_unique<MilkDecorator>(
std::make_unique<MilkDecorator>(
std::make_unique<SimpleCoffee>()
)
)
);
std::cout << "\nPremium Order:\n" << premiumCoffee->getDescription() << " costs: $" << premiumCoffee->getCost() << "\n";
return 0;
}
程序运行结果如下:
shell
$ g++ -o main main.cpp
$ ./main
--- Ordering Custom Coffees ---
Simple Coffee costs: $2
Simple Coffee, Milk costs: $2.5
Simple Coffee, Milk, Sugar costs: $2.75
Premium Order:
Simple Coffee, Milk, Milk, Sugar costs: $3.25