StructuralC++verifiedVerified

Decorator Pattern in C++

Attaches additional responsibilities to an object dynamically by wrapping it in decorator objects that share the same interface.

How to Implement the Decorator Pattern in C++

1Step 1: Define the Component interface

class DataSource {
public:
    virtual ~DataSource() = default;
    virtual std::string read() = 0;
    virtual void write(const std::string& data) = 0;
};

2Step 2: Concrete component

class FileDataSource : public DataSource {
    std::string data_;
public:
    std::string read() override { return data_; }
    void write(const std::string& data) override { data_ = data; }
};

3Step 3: Base decorator

class DataSourceDecorator : public DataSource {
protected:
    std::unique_ptr<DataSource> wrapped_;
public:
    explicit DataSourceDecorator(std::unique_ptr<DataSource> source)
        : wrapped_(std::move(source)) {}
    std::string read() override { return wrapped_->read(); }
    void write(const std::string& data) override { wrapped_->write(data); }
};

4Step 4: Concrete decorators

class EncryptionDecorator : public DataSourceDecorator {
public:
    using DataSourceDecorator::DataSourceDecorator;
    void write(const std::string& data) override {
        std::string encrypted = "[encrypted:" + data + "]";
        wrapped_->write(encrypted);
    }
    std::string read() override {
        auto data = wrapped_->read();
        // Simple "decryption" for demo
        return data;
    }
};

class CompressionDecorator : public DataSourceDecorator {
public:
    using DataSourceDecorator::DataSourceDecorator;
    void write(const std::string& data) override {
        std::string compressed = "[compressed:" + data + "]";
        wrapped_->write(compressed);
    }
};

int main() {
    // Stack decorators: compression -> encryption -> file
    auto source = std::make_unique<FileDataSource>();
    auto encrypted = std::make_unique<EncryptionDecorator>(std::move(source));
    auto compressed = std::make_unique<CompressionDecorator>(std::move(encrypted));

    compressed->write("Hello World");
    std::cout << compressed->read() << "\n";
}

Decorator Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Decorator Pattern in the Real World

Think of adding espresso shots and syrups to a coffee order. A plain coffee is the base component. Each addition—an espresso shot, vanilla syrup, oat milk—is a decorator that wraps the previous cup, adding its own cost and flavor. You can combine them in any order without the café needing a separate menu item for every combination.