结构
当客户端只在意CoreFunctionality.doThis()
,对OptionalOne.doThis()
或OptionalTwo.doThis()
并不关心。这时这些类会被Decorator基类所委托,而Decorator基类会以包含wrappee对象的方式进行委托。
具体操作
- 通常需要确保有一个核心控件,多个可选的装饰类以及一个接口
- 创建一个通用的接口
- 创建第二级基类(Decorator)用于支持可选的装饰类
- 核心类和Decorator类都从接口继承
- Decorator类与接口形成一种组合关系,而这个数据成员会在构造函数中被初始化
- 为每个装饰定义Decorator的子类
- Decorator子类实现了装饰的具体功能
- 客户端配置Core和Decorator对象的类型和顺序
案例
1.
#include <iostream>
using namespace std;
// 1. "lowest common denominator"
class Widget
{
public:
virtual void draw() = 0;
};
class TextField: public Widget
{
// 3. "Core" class & "is a"
int width, height;
public:
TextField(int w, int h)
{
width = w;
height = h;
}
/*virtual*/
void draw()
{
cout << "TextField: " << width << ", " << height << '\n';
}
};
// 2. 2nd level base class
class Decorator: public Widget // 4. "is a" relationship
{
Widget *wid; // 4. "has a" relationship
public:
Decorator(Widget *w)
{
wid = w;
}
/*virtual*/
void draw()
{
wid->draw(); // 5. Delegation
}
};
class BorderDecorator: public Decorator
{
public:
// 6. Optional embellishment
BorderDecorator(Widget *w): Decorator(w){}
/*virtual*/
void draw()
{
// 7. Delegate to base class and add extra stuff
Decorator::draw();
cout << " BorderDecorator" << '\n';
}
};
class ScrollDecorator: public Decorator
{
public:
// 6. Optional embellishment
ScrollDecorator(Widget *w): Decorator(w){}
/*virtual*/
void draw()
{
// 7. Delegate to base class and add extra stuff
Decorator::draw();
cout << " ScrollDecorator" << '\n';
}
};
int main()
{
// 8. Client has the responsibility to compose desired configurations
Widget *aWidget = new BorderDecorator(new BorderDecorator(new ScrollDecorator
(new TextField(80, 24))));
aWidget->draw();
}
Output
TextField: 80, 24
ScrollDecorator
BorderDecorator
BorderDecorator
2.
#include <iostream>
#include <string>
using namespace std;
class Interface
{
public:
virtual ~Interface(){}
virtual void write(string &) = 0;
virtual void read(string &) = 0;
};
class Core: public Interface
{
public:
~Core()
{
cout << "dtor-Core\n";
}
/*virtual*/void write(string &b)
{
b += "MESSAGE|";
}
/*virtual*/void read(string &);
};
class Decorator: public Interface
{
Interface *inner;
public:
Decorator(Interface *c)
{
inner = c;
}
~Decorator()
{
delete inner;
}
/*virtual*/void write(string &b)
{
inner->write(b);
}
/*virtual*/void read(string &b)
{
inner->read(b);
}
};
class Wrapper: public Decorator
{
string forward, backward;
public:
Wrapper(Interface *c, string str): Decorator(c)
{
forward = str;
string::reverse_iterator it;
it = str.rbegin();
for (; it != str.rend(); ++it)
backward += *it;
}
~Wrapper()
{
cout << "dtor-" << forward << " ";
}
void write(string &);
void read(string &);
};
int main()
{
Interface *object = new Wrapper(new Wrapper(new Wrapper(new Core(), "123"),
"abc"), "987");
string buf;
object->write(buf);
cout << "main: " << buf << endl;
object->read(buf);
delete object;
}
Output
main: 987]abc]123]MESSAGE|321]cba]789]
Wrapper: 987
Wrapper: abc
Wrapper: 123
Core: MESSAGE
Wrapper: 321
Wrapper: cba
Wrapper: 789
dtor-987 dtor-abc dtor-123 dtor-Core