Decorator (http://en.wikipedia.org/wiki/Decorator_pattern,aka, also known as Wrapper, an alternative naming shared with the Adapter pattern) is a structural pattern that allowsadding new behavior/functionality to an individual object atrun time, without affecting the behavior of objects from the same class.
-
subclass from Component class
-
in Decorator class add pointer of Component as its data member
-
in Decorator class’ ctor, pass in Component pointer to initialize this data member
-
in Decorator class, redirect all of its methods to “Component” pointer
-
in ConcreteDecorator, override any Component’s methods that needs to be modified
Alternative, subclassing, which add behavior at compile time, would result in exponential rise of new classes
-
This difference becomes most important when there areseveralindependent ways of extending functionality. Subclassing would mean that a new class would have to be made for every possible combination. By contrast, decorators are objects, created at runtime, and can be combined on a per-use basis
For example, if we have window class and wants to add scrollbar on window. At this point there is no real difference to add subclass scrollingWindow or have a decorator scrollingWindowDecorator. But what if we want to add border to ALL windows, then we have to create sublcass windowWithBoarder and scrollingWindowWithBoarder. Things will get worse with every new feature added.
#include "stdafx.h"
#include <string>
#include <iostream>
// abstract class define the functionalities, some of which will be modified by decorator
class Coffee
{
public:
virtual double cost() = 0;
virtual std::string getIntegridient() = 0;
virtual ~Coffee() {
}
virtual void print() {
std::cout << "Cost: " << cost() << "Integridient: " << getIntegridient() << std::endl;
}
};
// concrete class without any extra integridient
class SimpleCoffee : public Coffee
{
public:
virtual double cost() {
return 1;
}
virtual std::string getIntegridient() {
return "simple coffee";
}
};
// Decorators
class Decorator : public Coffee
{
public:
Decorator(Coffee* c)
: basicCoffee_(c) {
}
virtual double cost() {
return basicCoffee_->cost();
}
virtual std::string getIntegridient() {
return basicCoffee_->getIntegridient();
}
private:
Coffee *basicCoffee_;
};
class MilkDecorator : public Decorator
{
public:
MilkDecorator(Coffee *c)
: Decorator(c) {
}
virtual double cost() {
return Decorator::cost() + 0.5;
}
virtual std::string getIntegridient() {
return "Milk, " + Decorator::getIntegridient() ;
}
};
class WhipCoffee : public Decorator
{
public:
WhipCoffee(Coffee *c)
: Decorator(c) {
}
virtual double cost() {
return Decorator::cost() + 1;
}
virtual std::string getIntegridient() {
return "Whip, " + Decorator::getIntegridient() ;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
SimpleCoffee s;
s.print();
// decorated seperately
MilkDecorator m(&s);
m.print();
WhipCoffee w(&s);
w.print();
// test combinations
WhipCoffee wm(&m);
wm.print();
MilkDecorator mw(&w);
mw.print();
// is this desirable ?
MilkDecorator mm(&m);
mm.print();
return 0;
}
// Decorator2.cpp : another simple decorator example
//
#include "stdafx.h"
#include <iostream>
#include <string>
// base class
class Window
{
public:
virtual void draw() = 0;
virtual std::string getDescription() = 0;
virtual ~Window() {
}
virtual void print() {
std::cout << "DESCRIPTION: " << getDescription() << std::endl;
draw();
}
};
// (existing) concrete class
class SimpleWindow : public Window
{
public:
virtual void draw() {
std::cout << "Simple draw" << std::endl;
}
virtual std::string getDescription() {
return "Simple Window";
}
};
// decorators for Window classes, including the decorators themself
class Decorator : public Window
{
public:
Decorator(Window *w)
:win_(w) {
}
virtual void draw() {
win_->draw();
}
virtual std::string getDescription() {
return win_->getDescription();
}
private:
Window *win_;
};
class ScrollBarDecorator : public Decorator
{
public:
ScrollBarDecorator(Window *w)
: Decorator(w) {
}
virtual void draw() {
drawScrollBar();
Decorator::draw();
}
virtual std::string getDescription() {
return "scroll bar " + Decorator::getDescription();
}
private:
void drawScrollBar() {
std::cout<< "draw scroll bar " << std::endl;
}
};
class BoarderDecorator : public Decorator
{
public:
BoarderDecorator(Window *w)
:Decorator(w) {
}
virtual void draw() {
drawBoarder();
Decorator::draw();
}
virtual std::string getDescription() {
return "boarder " + Decorator::getDescription();
}
private:
void drawBoarder() {
std::cout << "draw boarder " << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
SimpleWindow sw;
sw.print();
ScrollBarDecorator sbsw(&sw);
sbsw.print();
BoarderDecorator bdsw(&sw);
bdsw.print();
BoarderDecorator bdsb(&sbsw);
bdsb.print();
return 0;
}