What should be at the top of inheritance tree of Decorator design pattern? I mean the base for both components and decorators
- non-abstract class: has data fields, implements methods
- abstract class: has data fields, has only abstract (pure virtual) methods
- interface: no data fields, has only abstract (pure virtual) methods
- abstract class & interface: interface is the base for decorator, abstract class is the base for decorated components
Simple example
IText
- interface declaresgetContent()
methodAbstractText
- abstract class declaresgetContent()
method and definestxt
data fieldText
- non-abstract class, general, can be also used as base for other classesHelloWorld
- non-abstract class, more specific thanText
HelloSomeone
- non-abstract class, extendsText
with the data fieldname
Decorator
abstract class for decorators (might be redundant?)PrefixDecorator
decorator class prefixesgetContent()
with a string prefixSuffixDecorator
decorator class suffixesgetContent()
with a string suffixgetContent()
method that should return txt with optional additional data (suffixes and prefixes from decorators,name
field in theHelloSomeone
class)
What base class should be chosen?
non-abstract class
abstract class
interface
abstract class & interface
Code for last example
#include <iostream>
#include <string>
using namespace std;
/* Base for decorator & abstract: no fields, getContent() is pure virtual */
class IText {
public:
virtual string getContent() = 0;
virtual ~IText() { }
};
/* Base: has a field, getContent() is pure virtual */
class AbstractText : public IText {
protected:
string txt;
public:
virtual ~AbstractText() { cout << " AbstractText dtor" << endl; }
AbstractText(string t = "...") : txt(t) { }
virtual string getContent() = 0;
};
/* Concrete, general */
class Text : public AbstractText {
public:
virtual ~Text() { cout << " Text dtor" << endl; }
Text(string t) : AbstractText(t) { }
virtual string getContent() { return txt; }
};
/* Concrete, more specific */
class HelloWorld : public AbstractText {
public:
virtual ~HelloWorld() { cout << " HelloWorld dtor" << endl; }
HelloWorld() : AbstractText("Hello world") {}
virtual string getContent() { return txt; }
};
/* Additional field */
class HelloSomeone : public AbstractText {
private:
string name;
public:
virtual ~HelloSomeone() { cout << " HelloSomeone dtor" << endl; }
HelloSomeone(string n) : AbstractText("Hello, "), name(n) { }
string getContent() { return (txt + name + "!"); }
};
class Decorator : public IText {
public:
virtual string getContent() = 0;
virtual ~Decorator() { cout << " Decorator dtor" << endl; }
};
class PrefixDecorator : public Decorator {
private:
IText *t;
public:
PrefixDecorator(IText *te) { t = te; }
virtual ~PrefixDecorator() { cout << " PrefixDecorator dtor" << endl; delete t; }
virtual string getContent() { return "---" + t->getContent(); }
};
class SuffixDecorator : public Decorator {
private:
IText *t;
public:
SuffixDecorator(IText *te) { t = te; }
virtual ~SuffixDecorator() { cout << " SuffixDecorator dtor" << endl; delete t; }
virtual string getContent() { return t->getContent() + "---"; }
};
int main() {
IText *t = new Text("some text");
IText *hw = new HelloWorld();
IText *hs = new HelloSomeone("Mark");
cout << t->getContent() << endl;
cout << hw->getContent() << endl;
cout << hs->getContent() << endl;
t = new PrefixDecorator(t);
hw = new PrefixDecorator(hw);
hw = new SuffixDecorator(hw);
cout << t->getContent() << endl;
cout << hw->getContent() << endl;
cout << "DELETE Text" << endl;
delete t;
cout << "DELETE Helloworld" << endl;
delete hw;
cout << "DELETE HelloSomeone" << endl;
delete hs;
}