C++ Decorator Pattern Example

In this article, we will learn how to use and implement the Decorator Pattern in C++ with an example.

Intent

  • Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
  • Client-specified embellishment of a core object by recursively wrapping it.
  • Wrapping a gift, putting it in a box, and wrapping the box.

C++ Decorator Pattern Example

The below diagram shows the generic structure of the Decorator Pattern:


Let's refer to the above structure to create an example to demonstrates the usage of the Decorator Pattern.
#include <iostream>

/*
 * Component
 * defines an interface for objects that can have responsibilities
 * added to them dynamically
 */
class Component
{
public:
    virtual ~Component() {}

    virtual void operation() = 0;
};

/*
 * Concrete Component
 * defines an object to which additional responsibilities
 * can be attached
 */
class ConcreteComponent : public Component
{
public:
    ~ConcreteComponent() {}

    void operation()
    {
        std::cout << "Concrete Component operation" << std::endl;
    }
};

/*
 * Decorator
 * maintains a reference to a Component object and defines an interface
 * that conforms to Component's interface
 */
class Decorator : public Component
{
public:
    ~Decorator() {}

    Decorator( Component *c ) : component( c ) {}

    virtual void operation()
    {
        component->operation();
    }

private:
    Component *component;
};

/*
 * Concrete Decorators
 * add responsibilities to the component (can extend the state
 * of the component)
 */
class ConcreteDecoratorA : public Decorator
{
public:
    ConcreteDecoratorA( Component *c ) : Decorator( c ) {}

    void operation()
    {
        Decorator::operation();
        std::cout << "Decorator A" << std::endl;
    }
};

class ConcreteDecoratorB : public Decorator
{
public:
    ConcreteDecoratorB( Component *c ) : Decorator( c ) {}

    void operation()
    {
        Decorator::operation();
        std::cout << "Decorator B" << std::endl;
    }
};


int main()
{
    ConcreteComponent  *cc = new ConcreteComponent();
    ConcreteDecoratorB *db = new ConcreteDecoratorB( cc );
    ConcreteDecoratorA *da = new ConcreteDecoratorA( db );

    Component *component = da;
    component->operation();

    delete da;
    delete db;
    delete cc;

    return 0;
}

Output

Concrete Component operation
Decorator B
Decorator A

When to Use Decorator Pattern

  • Use the Decorator pattern when you need to be able to assign extra behaviors to objects at runtime without breaking the code that uses these objects.
  •  Use the pattern when it’s awkward or not possible to extend an object’s behavior using inheritance.

Comments