I am learning the decorator pattern from the Head First Design Patterns book , and here’s what I’ve coded (C++) to get the pattern to work:
#include <iostream>
class AbstractType
{
public:
virtual double value() const = 0;
};
class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};
class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};
class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;
public:
DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject)
{}
DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject)
{}
virtual double value() const = 0;
const AbstractType& getObject() const
{
return *decoratedObject_;
}
};
class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
double value() const
{
const AbstractType& object = getObject();
return 1 + object.value();
}
};
class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
double value() const
{
const AbstractType& object = getObject();
return 2 + object.value();
}
};
using namespace std;
int main()
{
// When I decorate sequentially, it works fine
SecondConcreteType secondConc;
FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;
SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;
FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;
// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
//FirstDecoratorType firstDynamicDec (SecondConcreteType());
//cout << firstDynamicDec.value() << endl;
return 0;
};
In the main program, the object of theh ConcreteType must be created first, and then it is decorated using composition of the pointer to the AbstractType (within the DecoratorType). It works fine, if I create the concrete objects, and create the new decorated objects one after another..
What do I need to do in order for the DecoratorType to be able to decorate objects using composition in a single line of code (commented out line in the example code)? Would something like this be useful at all in the “real world”? I (obviously) don’t have a lot of experience in using design patterns.. so it’s difficult for me to see what functionality I should aim at.
EDIT:
Here’s a version working with basic pointers (valgrind shows no memory leaks, and states that no memory leaks are possible):
#include <iostream>
class AbstractType
{
public:
virtual double value() const = 0;
virtual ~AbstractType() {};
};
class FirstConcreteType
:
public AbstractType
{
public:
double value() const
{
return 1;
}
};
class SecondConcreteType
:
public AbstractType
{
public:
double value() const
{
return 2;
}
};
class DecoratorType
:
public AbstractType
{
const AbstractType* decoratedObject_;
bool own_;
public:
DecoratorType(const AbstractType& abstractObject)
:
decoratedObject_(&abstractObject),
own_(false)
{}
DecoratorType(const DecoratorType& decoratorObject)
:
decoratedObject_(&decoratorObject),
own_(false)
{}
DecoratorType (AbstractType* abstractPtr)
:
decoratedObject_(abstractPtr),
own_(true)
{}
DecoratorType (DecoratorType* decoratorPtr)
:
decoratedObject_(decoratorPtr),
own_(true)
{}
virtual ~DecoratorType()
{
if (own_)
{
delete decoratedObject_;
decoratedObject_ = 0;
}
}
virtual double value() const = 0;
const AbstractType& getObject() const
{
return *decoratedObject_;
}
};
class FirstDecoratorType
:
public DecoratorType
{
public:
FirstDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
FirstDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
FirstDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}
FirstDecoratorType (FirstDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}
double value() const
{
const AbstractType& object = getObject();
return 1 + object.value();
}
};
class SecondDecoratorType
:
public DecoratorType
{
public:
SecondDecoratorType(const AbstractType& abstractObject)
:
DecoratorType(abstractObject)
{}
SecondDecoratorType(const DecoratorType& decoratorObject)
:
DecoratorType(decoratorObject)
{}
SecondDecoratorType (AbstractType* abstractPtr)
:
DecoratorType(abstractPtr)
{}
SecondDecoratorType (SecondDecoratorType* decoratorPtr)
:
DecoratorType(decoratorPtr)
{}
double value() const
{
const AbstractType& object = getObject();
return 2 + object.value();
}
};
using namespace std;
int main()
{
// When I decorate sequentially, it works fine
SecondConcreteType secondConc;
FirstDecoratorType firstDec(secondConc);
cout << firstDec.value() << endl;
SecondDecoratorType secondDec(firstDec);
cout << secondDec.value() << endl;
FirstDecoratorType firstDecSecond (secondDec);
cout << firstDecSecond.value() << endl;
// Decorating in a single line, messes things up, since there is no
// constructor taking the value argument defined.
FirstDecoratorType firstDynamicDec (new SecondDecoratorType (
new FirstDecoratorType (new SecondConcreteType())));
cout << firstDynamicDec.value() << endl;
return 0;
};
The problem with this is that it does NOT define an object. Instead, it declares a function. Look for most-vexing-parse in C++ on this site, you will get lots of topics on it.
Short explanation : the function name is
firstDynamicDecwhose return type isFirstDecoratorTypeand it takes parameter which is again a function returningSecondConcreteTypeand taking no argument.