一、介绍
1.动机
在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合) 会导致更多子类的膨胀。
如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题,从而使得任何“功能扩展变化”所导致的影响将为最低?
2.定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承) 更为灵活(消除重复代码并减少子类个数)。——GOF
3.结构图
4.要点总结
通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
Decorator类在接口上表现为is-a的继承关系,即Decorator类继承了Component类所具有的接口;但在实现上又表现为has-a的组合关系,即Decorator类又使用了另外一个Component类。
Decorator模式的目的并非解决“多子类衍生的多继承”问题,其应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。
二、装饰模式
1.概念
装饰模式允许在不改变现有对象结构的情况下,动态地为对象添加额外的功能。
①装饰模式的优点:
- 提供了比继承更灵活的功能扩展机制。
- 通过使用不同的具体装饰类可以创造出很多不同行为的组合。
②装饰模式的缺点:
- 由于需要引入更多的类和对象,可能会增加系统的复杂度。
- 如果装饰器的层次结构设计不当,可能会导致维护困难。
2.实现要点
装饰模式实现要点:
- 抽象构件:定义了对象的接口,所有的具体构件都必须继承或实现这个接口。
- 具体构件:实现抽象构件的具体类,它是被装饰的对象。
- 抽象装饰:继承并组合抽象构件,可以通过其子类扩展具体构件的功能。
- 具体装饰:实现抽象装饰的相关方法,可传入具体构件对象以扩展其功能。
抽象装饰器使用组合是为了传入主体来实现装饰,使用继承是为了规范接口,同时保证包装后不改变原对象的本质。
3.示例
//抽象构件
class Coffee {
public:virtual string getName() = 0;virtual double cost() = 0;virtual ~Coffee() {}};//具体构件
class Espresso :public Coffee {
public:virtual string getName() override {return "Espresso";}virtual double cost() override {return 2.5;}
};//具体构件
class Americano :public Coffee {
public:virtual string getName() override {return "Americano";}virtual double cost() override {return 3.0;}
};//具体构件
class Latte :public Coffee {
public:virtual string getName() override {return "Latte";}virtual double cost() override {return 3.5;}
};//抽象装饰器
class CoffeeDecorator :public Coffee {
protected:Coffee* coffee;
public:CoffeeDecorator(Coffee* cof) :coffee(cof) {}virtual ~CoffeeDecorator() {delete coffee;}
};//具体装饰器
class SugarDecorator : public CoffeeDecorator {
public:SugarDecorator(Coffee* cof) :CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Sugar";}virtual double cost() override {return coffee->cost() + 0.2;}
};//具体装饰器
class MilkDecorator :public CoffeeDecorator {
public:MilkDecorator(Coffee* cof) :CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Milk";}virtual double cost() override {return coffee->cost() + 0.5;}
};//具体装饰器
class CreamDecorator :public CoffeeDecorator {
public:CreamDecorator(Coffee* cof): CoffeeDecorator(cof) {}virtual string getName() override {return coffee->getName() + " Cream";}virtual double cost() override {return coffee->cost() + 0.8;}
};
测试代码:
Coffee* espresso = new Espresso();
cout << espresso->getName() << " " << espresso->cost() << endl;
espresso = new SugarDecorator(espresso);
cout << espresso->getName() << " " << espresso->cost() << endl;
espresso = new MilkDecorator(espresso);
cout << espresso->getName() << " " << espresso->cost() << endl;
delete espresso;Coffee* americano = new Americano();
cout << americano->getName() << " " << americano->cost() << endl;
Coffee* americano1 = new SugarDecorator(americano);
cout << americano1->getName() << " " << americano1->cost() << endl;
Coffee* americano2 = new CreamDecorator(americano1);
cout << americano2->getName() << " " << americano2->cost() << endl;
delete americano2;Coffee* latte = new Latte();
cout << latte->getName() << " " << latte->cost() << endl;
MilkDecorator* milk = new MilkDecorator(latte);
cout << milk->getName() << " " << milk->cost() << endl;
CreamDecorator* cream = new CreamDecorator(milk);
cout << cream->getName() << " " << cream->cost() << endl;
delete cream;
输出结果:
Espresso 2.5
Espresso Sugar 2.7
Espresso Sugar Milk 3.2
Americano 3
Americano Sugar 3.2
Americano Sugar Cream 4
Latte 3.5
Latte Milk 4
Latte Milk Cream 4.8