定义:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
组成:
1.抽象构件角色(Component):定义一个抽象接口,以规范准备接收附加责任的对象。
2.具体构件角色(Concrete Component):这是被装饰者,定义一个将要被装饰增加功能的类。
3.装饰角色(Decorator):持有一个构件对象的实例,并定义了抽象定义的接口。
4.具体装饰角色(Concrete Decorator):负责给珈增加的功能。
//抽象基类,定义一个对象接口,可以为这个接口动态的添加职责。
class Component{
public:
Component(){}
virtual ~Comonent(){}
//纯虚函数,由派生类实现
vitual void Opation() = 0 ;
};
//抽象基类,维护一上指向Component对象的指针
class Decorator:publc Comonnt{
publc:
Decorator (Componnt* pComponent)
{
}
virtual ~Component(){
delete m_pComponent;
m_pComponent = NULL;
}
protected:
Compponnt *m_pComponent;
};
// 派生自Component,在这里表示需要给它动态添加职责的类
class ConcreateComponent
: public Component
{
public:
ConcreateComponent(){}
virtual ~ConcreateComponent(){}
virtual void Operation()
{
cout << "Operation of ConcreateComponent\n";
}
};
// 派生自Decorator,这里代表为ConcreateComponent动态添加职责的类
class ConcreateDecorator
: public Decorator
{
public:
ConcreateDecorator(Component* pComponent) : Decorator(pComponent){}
virtual ~ConcreateDecorator(){}
virtual void Operation()
{
m_pComponent->Operation();
AddedBehavior();
}
private:
void AddedBehavior()
{
cout << "AddedBehavior of ConcreateDecorator\n";
}
};
void main()
{
// 初始化一个Component对象
Component* pComponent = new ConcreateComponent();
// 采用这个Component对象去初始化一个Decorator对象,
// 这样就可以为这个Component对象动态添加职责
Decorator* pDecorator = new ConcreateDecorator(pComponent);
pDecorator->Operation();
delete pDecorator;
system("pause");
return 0;
}
透明和半透明
对于面向接口编程,应该尽量使客户程序不知道具体的类型,而应该对一个接口操作。
这样就要求装饰角色和具体装饰角色要满足Liskov 替换原则。像下面这样:
Component c = new ConcreteComponent();
Component c1 = new ConcreteDecorator(c);
JUnit 中就属于这种应用,这种方式被称为透明式。而在实际应用中,比如java.io 中往
往因为要对原有接口做太多的扩展而需要公开新的方法(这也是为了重用)。所以往往不能
对客户程序隐瞒具体的类型。这种方式称为“半透明式”。
//和我之前看的一个版本代码不是太一样,有点迷糊。说说我的想法和感受。从代码的结构来看,装饰者模式有一个主抽象基类Component,定义了一接口。有一个派生抽象在,维护了基类指针Decorator。派生类又有派生类
(ConcreateDecorator)用来实现Decorator;主抽象基类Component还有一个派生类用来基类接口,动态添加职责。