装饰者模式
动态的给对象修改功能。
UML图
实例代码
#include <iostream>
using namespace std;
/* Component (interface) */
class Widget {
public:
virtual void draw() = 0;
virtual ~Widget() {}
};
/* ConcreteComponent */
class TextField : public Widget {
private:
int width, height;
public:
TextField( int w, int h ){
width = w;
height = h;
}
void draw() {
cout << "TextField: " << width << ", " << height << '\n';
}
};
/* Decorator (interface) */
class Decorator : public Widget {
private:
Widget* wid; // reference to Widget
public:
Decorator( Widget* w ) {
wid = w;
}
void draw() {
wid->draw();
}
~Decorator() {
delete wid;
}
};
/* ConcreteDecoratorA */
class BorderDecorator : public Decorator {
public:
BorderDecorator( Widget* w ) : Decorator( w ) { }
void draw() {
Decorator::draw();
cout << " BorderDecorator" << '\n';
}
};
/* ConcreteDecoratorB */
class ScrollDecorator : public Decorator {
public:
ScrollDecorator( Widget* w ) : Decorator( w ) { }
void draw() {
Decorator::draw();
cout << " ScrollDecorator" << '\n';
}
};
int main( void ) {
Widget* aWidget = new BorderDecorator(
new BorderDecorator(
new ScrollDecorator(
new TextField( 80, 24 ))));
aWidget->draw();
delete aWidget;
}
问题在哪里?我为什么会感觉扯到蛋了!!!
例子中的operator只有一个draw()
。如果有100个operator,我们必须在装饰者类里面把100个都实现一次。
class Decorator : public Widget {
private:
Widget* wid; // reference to Widget
public:
Decorator( Widget* w ) {
wid = w;
}
void draw() {
wid->draw();
}
void fun1(){
wid->fun1();
};
void fun2(){
wid->fun2();
};
......
void fun100(){
wid->fun100();
};
~Decorator() {
delete wid;
}
};
实际上我TM只是想改其中的一个函数draw()
,给他加上一个log图形而已。但是其他的funx()
必须还是得写,因为装饰者返回了新对象,基类中的数据成员都是空的,未初始化的。不写的话数据就对不上了。所以为了动态修改对象的一个功能,我需要重写这个对象的其他99个方法,是不是分分钟要捏蛋自尽了。
关键问题
装饰者和被装饰者都是继承于同一个父类,有相同的方法,区别在于对象里面的数据不同。那么我能不能把对象里面的数据复制过来?
可以通过memcpy来复制对象里面数据。为啥?因为memcpy可以绕过类的访问权限问题。
#include "iostream"
using namespace std;
class Base
{
public:
virtual void fun(){
cout<<"base fun call"<<endl;
}
virtual void printMD(){
cout<<"base say MD: "<<_a<<endl;
}
virtual void setInt(int a){
_a = a;
}
protected:
int _a;
char *p;
};
class A:public Base
{
public:
void fun(){
Base::fun();
cout<<"A fun call"<<endl;
}
};
class B:public Base
{
public:
void fun(){
Base::fun();
cout<<"B fun call"<<endl;
}
};
template <typename T>
//不要问我为什么用X,我只是觉得叼而已
class X:public T
{
public:
X(T *t):_t(t){
char *dst = (char *)this;
char *src = (char *)_t;
memcpy((void *)(dst + sizeof(char *)), (void *)(src + sizeof(char *)), sizeof(T) - sizeof(char *));
};
T *getInstance(){
return this;
}
//只实现fun函数,不实现printMD
void fun(){
_t->fun();
cout<<"X fun call"<<endl;
}
protected:
T *_t;
};
int main()
{
A *a = new A();
cout<<"------before----"<<endl;
a->fun();
a->setInt(5);
a->printMD();
cout<<"------after-----"<<endl;
a = (new X<A>(a))->getInstance();
a->fun();
cout<<"~~~~~~~~~~~~~~~~~"<<endl;
a->printMD();
B *b = new B();
b = (new X<B>(b))->getInstance();
b->fun();
b->printMD();
return 0;
}
输出结果
------before----
base fun call
A fun call
base say MD: 5
------after-----
base fun call
A fun call
X fun call
~~~~~~~~~~~~~~~~~
base say MD: 5
base fun call
B fun call
X fun call
base say MD: 0
可以看出波浪线下面的base say MD:5
,说明成员变量_a
被拷贝到装饰者里面去了。但是我的装饰者只实现了fun
函数。