装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
--《Head First 设计模式》
装饰者模式简单来说就是对已有的类进行拓展但有不要求修改已有的类的代码,也就是符合了“对扩展开放,对修改关闭”的设计原则。
装饰者模式的优缺点:
优点
1、装饰者模式可以提供比继承更多的灵活性
2、可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
3、通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
缺点
1、会产生很多的小对象,增加了系统的复杂性
2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
装饰者模式的使用场景
1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2、需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
(以上内容来源于网络)
C++实现装饰者模式:
场景:原有饮料类,咖啡类继承了饮料了。现在需要添加调料类,为咖啡添加调料,要求不能修改原有的类。
#ifndef __BEVERAGE_H__
#define __BEVERAGE_H__
#include <string>
/*
* 饮料类
*/
class Beverage
{
public:
virtual std::string getDescription() const
{
return description;
}
virtual double cost() = 0;
public:
std::string description = "Unknow Beverage";
};
#endif
#ifndef __COFFEE_H__
#define __COFFEE_H__
//咖啡类
#include "beverage.h"
//浓咖啡
class Espresso : public Beverage
{
public:
Espresso();
~Espresso();
virtual std::string getDescription() const override;
virtual double cost() override;
};
//黑咖啡
class HouseBlend : public Beverage
{
public:
HouseBlend();
~HouseBlend();
virtual std::string getDescription() const override;
virtual double cost() override;
};
#endif
//咖啡实现类
#include "coffee.h"
Espresso::Espresso()
{
description = "Espresso";
}
Espresso::~Espresso()
{
}
std::string Espresso::getDescription() const
{
return description;
}
double Espresso::cost()
{
return 1.99;
}
HouseBlend::HouseBlend()
{
description = "HouseBlend";
}
HouseBlend::~HouseBlend()
{
}
std::string HouseBlend::getDescription() const
{
return description;
}
double HouseBlend::cost()
{
return .89;
}
以下是调味料的实现:
#ifndef __CONDIMENTDECORATOR_H__
#define __CONDIMENTDECORATOR_H__
#include <string>
#include "beverage.h"
//调料装饰类
class CondimentDecorator : public Beverage
{
public:
virtual std::string getDescription() const override = 0;
virtual double cost() override = 0;
};
//调料--摩卡
class Mocha : public CondimentDecorator
{
public:
explicit Mocha(Beverage* beverage);
~Mocha();
virtual std::string getDescription() const override;
virtual double cost() override;
private:
Beverage* m_beverage;
};
//调料--牛奶
class Milk : public CondimentDecorator
{
public:
explicit Milk(Beverage* beverage);
~Milk();
virtual std::string getDescription() const override;
virtual double cost() override;
private:
Beverage* m_beverage;
};
#endif
#include "condimentdecorator.h"
Mocha::Mocha(Beverage* beverage):m_beverage(beverage)
{
}
Mocha::~Mocha()
{
}
std::string Mocha::getDescription() const
{
return m_beverage->getDescription() + ",Mocha";
}
double Mocha::cost()
{
return m_beverage->cost() + .20;
}
Milk::Milk(Beverage* beverage):m_beverage(beverage)
{
}
Milk::~Milk()
{
}
std::string Milk::getDescription() const
{
return m_beverage->getDescription() + ",Milk";
}
double Milk::cost()
{
return m_beverage->cost() + .50;
}
生产咖啡并添加调料:
#include <iostream>
#include "beverage.h"
#include "coffee.h"
#include "condimentdecorator.h"
using namespace std;
int main()
{
Beverage* beverage = new Espresso();
Beverage* beverage2 = new HouseBlend();
cout << beverage->getDescription() << " and cost = "
<< beverage->cost() << endl;
cout << beverage2->getDescription() << " and cost = "
<< beverage2->cost() << endl;
//为HouseBlend的咖啡加上摩卡
beverage2 = new Mocha(beverage2);
cout << beverage2->getDescription() << " and cost = "
<< beverage2->cost() << endl;
//再为加了摩卡的HouseBlend咖啡加上牛奶
beverage2 = new Milk(beverage2);
cout << beverage2->getDescription() << " and cost = "
<< beverage2->cost() << endl;
delete beverage;
delete beverage2;
return 0;
}
Linux下编译:
g++ -std=c++11 -o main main.cc coffee.cc condimentdecorator.cc
./main
结果是:
Espresso and cost = 1.99 //没有加调料的浓咖啡
HouseBlend and cost = 0.89 //没有加调料的黑咖啡
HouseBlend,Mocha and cost = 1.09 //加了摩卡的黑咖啡
HouseBlend,Mocha,Milk and cost = 1.59 //加了摩卡和牛奶的黑咖啡