欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > C++设计模式(装饰模式)

C++设计模式(装饰模式)

2024/11/30 7:01:25 来源:https://blog.csdn.net/2301_82023822/article/details/143890836  浏览:    关键词:C++设计模式(装饰模式)

一、介绍

1.动机

在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合) 会导致更多子类的膨胀。

如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题,从而使得任何“功能扩展变化”所导致的影响将为最低?

 

2.定义

动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承) 更为灵活(消除重复代码并减少子类个数)。——GOF

 

3.结构图

0167c308773d43d48182a8d411022685.jpeg

 

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

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com