装饰
动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。
实例
main.cc:
#include "Headband_decorator.h"
#include "cuff_decorator.h"
#include "cool_runner.h"
#include <windows.h>
/*
design_pattern:"decorate"
When running, everyone will bring some of the effects of the equipment, such as headband, cuff...
*/
int main(){
Runner *runner = new CoolRunner();
Runner *cuff_decorator = new CuffDecorator(runner);
Runner *headband_decorator = new HeadbandDecorator(cuff_decorator);
headband_decorator->Show();
system("Pause");
return 0;
}
Runner:
//runner.h
#ifndef HELENDP_SOURCE_RUNNER_H_
#define HELENDP_SOURCE_RUNNER_H_
class Runner{
public:
Runner();
virtual ~Runner();
virtual void Show();
};
#endif
//runner.cc
#include "runner.h"
#include <iostream>
using namespace std;
Runner::Runner(){
}
Runner::~Runner(){
}
void Runner::Show(){
cout << "Runner::Show" << endl;
}
CoolRunner:
//cool_runner.h
#ifndef HELENDP_SOURCE_COOL_RUNNER_H_
#define HELENDP_SOURCE_COOL_RUNNER_H_
#include "runner.h"
class CoolRunner : public Runner{
public:
CoolRunner();
~CoolRunner();
void Show();
};
#endif
//cool_runner.cc
#include "cool_runner.h"
#include <iostream>
using namespace std;
CoolRunner::CoolRunner(){
}
CoolRunner::~CoolRunner(){
}
void CoolRunner::Show(){
cout << "CoolRunner::Show:" << endl;
}
Decorator:
//decorator.h
#ifndef HELENDP_SOURCE_DECORATOR_H_
#define HELENDP_SOURCE_DECORATOR_H_
#include "runner.h"
class Decorator : public Runner{
public:
Decorator(Runner *runner);
~Decorator();
void Show();
private:
Runner *runner_;
};
#endif
//decorator.cc
#include "decorator.h"
Decorator::Decorator(Runner * runner){
runner_ = runner;
}
Decorator::~Decorator(){
}
void Decorator::Show(){
runner_->Show();
}
CuffDecorator:
//cuff_decorator.h
#ifndef HELENDP_SOURCE_CUFF_DECORATOR_H_
#define HELENDP_SOURCE_CUFF_DECORATOR_H_
#include "decorator.h"
class CuffDecorator : public Decorator{
public:
CuffDecorator(Runner *runner);
~CuffDecorator();
void Show();
private:
void CuffShow();
};
#endif
//cuff_decorator.cc
#include "cuff_decorator.h"
#include <iostream>
using namespace std;
CuffDecorator::CuffDecorator(Runner * runner) : Decorator(runner){
}
CuffDecorator::~CuffDecorator(){
}
void CuffDecorator::CuffShow(){
cout << "I have cuff!" << endl;
}
void CuffDecorator::Show(){
Decorator::Show();
CuffShow();
}
HeadbandDecorator:
//headband_decorator.h
#ifndef HELENDP_SOURCE_HEADBAND_DECORATOR_H_
#define HELENDP_SOURCE_HEADBAND_DECORATOR_H_
#include "decorator.h"
class HeadbandDecorator : public Decorator{
public:
HeadbandDecorator(Runner *runner);
~HeadbandDecorator();
void Show();
private:
void HeadbandShow();
};
#endif
//headband_decorator.cc
#include "headband_decorator.h"
#include <iostream>
using namespace std;
HeadbandDecorator::HeadbandDecorator(Runner * runner) : Decorator(runner){
}
HeadbandDecorator::~HeadbandDecorator(){
}
void HeadbandDecorator::HeadbandShow(){
cout << "I have headband!" << endl;
}
void HeadbandDecorator::Show(){
Decorator::Show();
HeadbandShow();
}
代码和UML图(EA)工程文件,最后会整理打包上传.
UML类图
结构
- Component(Runner):对象接口.
- ConcreteComponent(CoolRunner):具体对象,可以给这个对象添加一些职责.
- Decorator(Decorator):装饰类.
- ConcreteDecorator(CuffDecorator,HeadbandDecorator):向ConcreteComponent具体添加的职责.
优点
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性.
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为.
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象.
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”.
缺点
- 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,同时还将产生很多具体装饰类。这些装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度.
- 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐.