装饰模式(Decorator):
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
1. Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteComponent就是具体的装饰对象,起到给Component添加职责的功能。
2. 装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链中。
3. 如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类,同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。
接下来就是用代码实现一下上面的UML结构图。
装饰模式实现代码:
#pragma once
#include <iostream>
using namespace std;
class CComponent
{
public:
virtual void Operation() = 0;
};
class CConcreteComponent : public CComponent
{
public:
void Operation()
{
cout<<"具体对象的操作"<<endl;
}
};
class CDecorator : public CComponent
{
private:
CComponent * m_pComponent;
public:
CDecorator()
{
m_pComponent = NULL;
}
void SetComponent(CComponent * pComponent)
{
m_pComponent = pComponent;
}
void Operation()
{
if(m_pComponent != NULL)
{
m_pComponent->Operation();
}
}
};
class CConcreteDecoratorA : public CDecorator
{
private:
string m_strAddedState;//独有功能,区别于CConcreteDecoratorB
public:
void Operation()
{
CDecorator::Operation();//这句好好理解下(提示:每个对象都会有这个动作)
cout<<"具体装饰对象A的操作"<<endl;
}
};
class CConcreteDecoratorB : public CDecorator
{
private:
void AddeBehavior() //具体区别于A对象的操作
{
return ;
}
public:
void Operation()
{
CDecorator::Operation();//这句好好理解下(提示:每个对象都会有这个动作)
cout<<"具体装饰对象B的操作"<<endl;
}
};
客户端调用代码:
#include "stdafx.h"
#include "DecoratorMode.h"
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
//理解为穿衣服
CConcreteComponent *pPeople = new CConcreteComponent();
CConcreteDecoratorA *pClothesA = new CConcreteDecoratorA();
CConcreteDecoratorB *pClothesB = new CConcreteDecoratorB();
// 人 -> 穿A衣服 -> 穿B衣服
pClothesA->SetComponent(pPeople);
pClothesB->SetComponent(pClothesA);
pClothesB->Operation();
delete pPeople ,delete pClothesA ,delete pClothesB;
return 0;
}
执行结果:
总结:
装饰模式是为已有功能动态地添加更多功能的一种方式。当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码代码通常装饰了原有类的核心职责或者主要行为,在主类中加入了新的字段,新的昂发和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此。当需要执行特殊行为时,客户端代码就可以在运行时根据需要有选择地,按顺序地使用装饰功能包装对象了。
那么也就是装饰模式的优点是有效地吧类的核心职责和装饰功能区分开了。而且可以去除相关类中重复装饰的逻辑。
至于缺点,书上没有说,其实很容易发现,用户无论装饰什么,前提是必须知道所有衣服吧,当前的这个模式是用户必须把衣服new出来(当然可以工厂优化,不过这样这个模式太繁琐了),以至于增加了用户和改功能实现模块之间的耦合度。