装饰者模式

来源:互联网 发布:中国森林覆盖率 知乎 编辑:程序博客网 时间:2024/04/30 09:28

请先理解为什么要引入装饰者模式?

装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。


我们以饮料为主体,然后在运行时以调料来装饰饮料。


注意:

1.装饰者和被装饰者有相同的超类型。

2.可以用一个或多个装饰者包装一个对象。

3.在任何需要原始对象(被包装)的场合,可以用装饰过的对象代替它。

4.装饰者可以在所委托被装饰者的行为之前与(或)之后,加上自己的行为,已达到特定的目的。

5.对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。


注意这句话:
每个包装者都有一个(包装一个)组件,也就是说,装饰者有一个实例变量以保存某个Component的引用。

下面来看饮料对应的类图:


注意:

将装饰者与组件组合时,就是在加入新的行为。所得到的新行为,并不是继承自超类,而是有组合对象得来的。

Beverage和CondimentDecorator都是抽象类。

下面是调料(装饰者)的代码:

class Mocha :public CondimentDecorator{private:Beverage beverage;                  //用一个实例变量记录饮料,也就是被装饰者public:Mocha(Beverage beverage)            //把饮料当做构造器的参数{this.beverage = beverage;}string getDescription(){return beverage.getDescription() + ", Mocha";  //这就是“委托”达到继承效果}double cost(){return 0.20 + beverage.cost();  //首先把调用委托给被装饰对象,然后再加上Mocha的价钱}};

下面是整体实现,但是存在内存泄漏,可以考虑用智能指针。

#include <iostream>#include <vector>#include <string>#include <list>using namespace std;/*饮料(beverage)抽象类*/class Beverage{protected:string description = "Unknown Beverage";public:virtual string getDescription(){ return description; }virtual double cost() = 0;};/*浓缩咖啡(espresso)类*/class Espresso :public Beverage {public:Espresso(){ description = "Espresso"; }double cost(){ return 1.99; }};/*House Blend Coffee类*/class HouseBlend :public Beverage{public:HouseBlend(){ description = "House Blend Coffee"; }double cost(){ return .89; }};/*DaikRoast 类*/class DaikRoast :public Beverage{public:DaikRoast(){ description = "Daik Roast Coffee"; }double cost(){ return 1.89; }};/*Decat 类*/class Decat :public Beverage{public:Decat(){ description = "Decat Coffee"; }double cost(){ return .99; }};/*调料(condiment)抽象类,也即装饰者类*/class CondimentDecorator :public Beverage{//装饰者和被装饰者“类型匹配”,所以public继承virtual string getDescription() = 0;};/*注意下面的实现,就用到了委托的办法,先委托给被装饰对象,计算结果后再加上装饰者的*/class Mocha :public CondimentDecorator{private:Beverage *beverage;   //has apublic:Mocha(Beverage *_beverage) :beverage(_beverage){}string getDescription(){ return beverage->getDescription() + ", Mocha"; }double cost(){ return .20 + beverage->cost(); }};class Whip :public CondimentDecorator{private:Beverage *beverage;   //has apublic:Whip(Beverage *_beverage) :beverage(_beverage){}string getDescription(){ return beverage->getDescription() + ", Whip"; }double cost(){ return .50 + beverage->cost(); }};class Soy :public CondimentDecorator{private:Beverage *beverage;   //has apublic:Soy(Beverage *_beverage) :beverage(_beverage){}string getDescription(){ return beverage->getDescription() + ", Soy"; }double cost(){ return .30 + beverage->cost(); }};int main(void){ Beverage *beverage = new Espresso();cout << beverage->getDescription() << " $" << beverage->cost() << endl;Beverage *beverage2 = new Espresso();beverage2 = new Mocha(beverage2);beverage2 = new Mocha(beverage2);beverage2 = new Whip(beverage2);cout << beverage2->getDescription() << " $" << beverage2->cost() << endl;Beverage *beverage3 = new Espresso();beverage3 = new Soy(beverage3);beverage3 = new Mocha(beverage3);beverage3 = new Whip(beverage3);cout << beverage3->getDescription() << " $" << beverage3->cost() << endl;delete beverage;delete beverage2;delete beverage3;_CrtDumpMemoryLeaks(); //检测是否有内存泄漏return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 看不下去书怎么办 职高读不下去怎么办 小孩不主动说话怎么办 不喜欢自己的儿子怎么办 生了儿子不喜欢怎么办 孩子不愿意去幼儿园怎么办 内向妈妈带孩子怎么办 从小就不爱学习怎么办 孩子老爱玩不爱学习怎么办? 孩子不爱做题怎么办 看书静不下心怎么办 孩子不自觉学习怎么办 不自觉的孩子怎么办 不学习的孩子怎么办 电脑不受老师控制怎么办 儿子不尊重老师怎么办 小孩不喜欢吃蔬菜怎么办 小孩不愿练钢琴怎么办 孩子不喜欢幼儿园老师怎么办 孩子不主动思考怎么办 我初一不想读书怎么办 初中孩子不爱学习怎么办 初一就不想读书怎么办 孩子懒得写作业怎么办 初中学生讨厌学习怎么办? 小学不写作业怎么办 幼儿园小朋友不愿意上学怎么办 幼儿园孩子不愿意上学怎么办 宝宝不愿意上幼儿园怎么办 孩子不爱上幼儿园怎么办 宝宝不爱上幼儿园怎么办 宝宝不爱去幼儿园怎么办 幼儿园宝宝不爱写字怎么办 小孩贪玩不爱学习怎么办 老师对幼儿不好怎么办 小孩不愿写作业怎么办 小孩怕老师厌学怎么办 幼儿园怕老师厌学怎么办 孩子很怕老师怎么办 孩子怕外教老师怎么办 家长打老师老师怎么办