概念
装饰者模式动态地将责任附加到对象上. 如要扩展功能, 装饰者提供了比继承更有弹性的替代方案.
装饰者与和被装饰者必须有相同的超类, 这是相当关键的地方, 在此模式中, 我们利用继承达到"类型匹配", 而不是利用继承来获得"行为"
适用场景
1 在不影响其他对象的情况下,以动态、透明的方式给单个对象(或一个类)添加职责。
2 需要动态的给一个类添加功能, 这些功能可以撤销
3 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实
4当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类.
结构
抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,
即可以给这些对象动态地添加职责。
具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。
可以给这个类的对象添加一些职责
抽象装饰器(Decorator):维持一个指向构件Component对象的实例,
并定义一个与抽象组件角色Component接口一致的接口
具体装饰器角色(ConcreteDecorator):向组件添加职责。
特点
1 装饰者和被装饰对象有相同的超类型,
2 可以用一个或多个装饰者包装一个对象
3 由于装饰者和被装饰者有相同的超类型, 所以在任何需要原始对象(被包装的)的场合, 可以用装饰过的对象代替它
4 装饰者可以在所委托被装饰者的行为之前与/或之后, 加上自己的行为, 以达到特定的目的
5 对象可以在任何时候被装饰, 所以可以在运行时动态的, 不限量的使用你喜欢的装饰者来装饰对象.
优缺点
优点:
1 比静态继承更灵活: 与对象的静态继承(多重继承)相比, Decorator模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。相比之下,继承机制要求为每个添加的职责创建一个新的子类。这会产生许多新的类,并且会增加系统的复杂度。此外,为一个特定的Component类提供多个不同的 Decorator类,这就使得你可以对一些职责进行混合和匹配。使用Decorator模式可以很容易地重复添加一个特性。
2 避免在层次结构高层的类有太多的特征, Decorator模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用 Decorator类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。这样,应用程序不必为不需要的特征付出代价。同时更易于不依赖于 Decorator所扩展(甚至是不可预知的扩展)的类而独立地定义新类型的 Decorator。扩展一个复杂类的时候,很可能会暴露与添加的职责无关的细节。
2 避免在层次结构高层的类有太多的特征, Decorator模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用 Decorator类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能。这样,应用程序不必为不需要的特征付出代价。同时更易于不依赖于 Decorator所扩展(甚至是不可预知的扩展)的类而独立地定义新类型的 Decorator。扩展一个复杂类的时候,很可能会暴露与添加的职责无关的细节。
缺点:
1 如果代码针对特定种类的具体组件, 做一些特殊的事, 一旦用装饰者包装, 就会造成类型改变。
2 装饰者会导致设计中出现许多小对象, 如果过度使用, 会让程序变得很复杂.
1 如果代码针对特定种类的具体组件, 做一些特殊的事, 一旦用装饰者包装, 就会造成类型改变。
2 装饰者会导致设计中出现许多小对象, 如果过度使用, 会让程序变得很复杂.
例子
Starbuzz咖啡店的订单, 主要目的是为了向各种饮料中假如其他调料,比如, 加入摩卡和奶泡的咖啡....,
#include <iostream>
#include <string>
#include <memory>
#pragma execution_character_set("utf-8")
using namespace std;
class Beverage
{
public:
virtual string description() const
{
return "unknown beverage";
}
virtual double cost() const = 0;
};
// 具体组件
class Espresso : public Beverage
{
public:
string description() const override
{
return "Espresso";
}
double cost() const override
{
return 1.99;
}
};
class HouseBlend : public Beverage
{
public:
string description() const override
{
return "House Blend Coffee";
}
double cost() const
{
return 0.89;
}
};
class DarkRoast : public Beverage
{
public:
string description() const override
{
return "Dark Roast Coffee";
}
double cost() const
{
return 0.99;
}
};
// 调料装饰者基类, 目的是让所有装饰者重新实现description函数
class CondimentDecorator: public Beverage
{
public:
explicit CondimentDecorator(shared_ptr<Beverage> beverage)
: m_beverage(beverage)
{
if(!beverage)
{
throw ;
}
}
virtual ~CondimentDecorator()
{
}
string description() const override = 0 ;
protected:
const shared_ptr<Beverage> component() const
{
return m_beverage;
}
private:
shared_ptr<Beverage> m_beverage;
};
// 装饰者
class Mocha : public CondimentDecorator
{
public:
using CondimentDecorator::CondimentDecorator;
string description() const override
{
return component()->description() + ", Mocha";
}
double cost() const override
{
return 0.20 + component()->cost();
}
};
class Whip : public CondimentDecorator
{
public:
using CondimentDecorator::CondimentDecorator;
string description() const override
{
return component()->description() + ", Whip";
}
double cost() const override
{
return 0.10 + component()->cost();
}
};
class Soy : public CondimentDecorator
{
public:
using CondimentDecorator::CondimentDecorator;
string description() const override
{
return component()->description() + ", Soy";
}
double cost() const override
{
return 0.15 + component()->cost();
}
};
int main()
{
auto print = [](const shared_ptr<Beverage> &beverage)
{
if(!beverage) throw;
cout << beverage->description() << " $ " << beverage->cost() << endl;
};
shared_ptr<Beverage> b1 = make_shared<DarkRoast>();
b1 = make_shared<Mocha>(b1);
b1 = make_shared<Mocha>(b1);
b1 = make_shared<Whip>(b1);
print(b1);
shared_ptr<Beverage> b2 = make_shared<HouseBlend>();
b2 = make_shared<Soy>(b2);
b2 = make_shared<Mocha>(b2);
b2 = make_shared<Whip>(b2);
print(b2);
return 0;
}