c++设计模式:装饰者模式(Decorator Pattern)

定义:

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

场景:

我们购买咖啡的时候,可以要求在其中加入各种调料,例如:蒸奶、豆浆、摩卡或覆盖奶泡,而咖啡店也会根据所加入的调料收取不同的费用,所以当我们设计订单系统的时候就需要考虑到这些调料部分啦。顾客的需求不一,如果我们针对每种配方都声明一个类得话,系统的维护将会十分头疼。此时装饰者模式就派上用场啦。我们可以根据顾客的需要动态的扩展顾客定制的咖啡,让其加上不同的调料,最终计算出顾客所需缴纳的费用。它的实现有点类似于递归,在实际使用的时候可以慢慢体会。

类图:

c++代码如下:

不使用指针版本:

复制代码
#include <iostream>
#include <string>
using namespace std;

class Beverage
{
public:
    virtual ~Beverage() {};
    virtual string getDescription(); // 必须是虚函数,否则会造成后期使用时描述显示不正确
    virtual double cost() = 0;
protected:
    string m_description;
};

class CondimentDecorator:public Beverage
{
public:
    virtual string getDescription() = 0;
};

class Espresso:public Beverage
{
public:
    Espresso();
    double cost();
};

class HouseBlend:public Beverage
{
public:
    HouseBlend();
    double cost();
};

class DarkRoast:public Beverage
{
public:
    DarkRoast();
    double cost();
};

class Decaf:public Beverage
{
public:
    Decaf();
    double cost();
};

class Mocha:public CondimentDecorator
{
public:
    Mocha(Beverage* pBeverage);
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Milk:public CondimentDecorator
{
public:
    Milk(Beverage* pBeverage);
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Soy:public CondimentDecorator
{
public:
    Soy(Beverage* pBeverage);
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Whip:public CondimentDecorator
{
public:
    Whip(Beverage* pBeverage);
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

string Beverage::getDescription()
{
    return m_description;
}

Espresso::Espresso()
{
    m_description = "Espresso";
}

double Espresso::cost()
{
    return 1.99;
}

HouseBlend::HouseBlend()
{
    m_description = "House Blend Coffee";
}

double HouseBlend::cost()
{
    return 0.89;
}

DarkRoast::DarkRoast()
{
    m_description = "Dark Roast Coffee";
}

double DarkRoast::cost()
{
    return 0.99;
}

Decaf::Decaf()
{
    m_description = "Decaf Coffee";
}

double Decaf::cost()
{
    return 1.05;
}

Mocha::Mocha(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

string Mocha::getDescription()
{
    return m_pBeverage->getDescription() + " + Mocha";
}

double Mocha::cost()
{
    return 0.20 + m_pBeverage->cost();
}

Milk::Milk(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

string Milk::getDescription()
{
    return m_pBeverage->getDescription() + " + Milk";
}

double Milk::cost()
{
    return 0.10 + m_pBeverage->cost();
}

Soy::Soy(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

string Soy::getDescription()
{
    return m_pBeverage->getDescription() + " + Soy";
}

double Soy::cost()
{
    return 0.15 + m_pBeverage->cost();
}

Whip::Whip(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

string Whip::getDescription()
{
    return m_pBeverage->getDescription() + " + Whip";
}

double Whip::cost()
{
    return 0.10 + m_pBeverage->cost();
}

int main()
{
    Espresso espresso;
    cout << espresso.getDescription() << " $" << espresso.cost() << endl;

    DarkRoast darkRoast;
    Mocha mocha1(&darkRoast);
    Mocha mocha2(&mocha1);
    Whip whip1(&mocha2);
    cout << whip1.getDescription() << " $" << whip1.cost() << endl;

    HouseBlend houseBlend;
    Soy soy1(&houseBlend);
    Mocha mocha3(&soy1);
    Whip whip2(&mocha3);
    cout << whip2.getDescription() << " $" << whip2.cost() << endl;

    return 0;
}
复制代码

 

使用指针版本:

 

复制代码
#include <iostream>
#include <string>
using namespace std;

class Beverage
{
public:
    virtual ~Beverage() {};
    virtual string getDescription();
    virtual double cost() = 0;
protected:
    string m_description;
};

class CondimentDecorator:public Beverage
{
public:
    virtual string getDescription() = 0;
};

class Espresso:public Beverage
{
public:
    Espresso();
    double cost();
};

class HouseBlend:public Beverage
{
public:
    HouseBlend();
    double cost();
};

class DarkRoast:public Beverage
{
public:
    DarkRoast();
    double cost();
};

class Decaf:public Beverage
{
public:
    Decaf();
    double cost();
};

class Mocha:public CondimentDecorator
{
public:
    Mocha(Beverage* pBeverage);
    ~Mocha();
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Milk:public CondimentDecorator
{
public:
    Milk(Beverage* pBeverage);
    ~Milk();
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Soy:public CondimentDecorator
{
public:
    Soy(Beverage* pBeverage);
    ~Soy();
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

class Whip:public CondimentDecorator
{
public:
    Whip(Beverage* pBeverage);
    ~Whip();
    string getDescription();
    double cost();
protected:
    Beverage* m_pBeverage;
};

string Beverage::getDescription()
{
    return m_description;
}

Espresso::Espresso()
{
    m_description = "Espresso";
}

double Espresso::cost()
{
    return 1.99;
}

HouseBlend::HouseBlend()
{
    m_description = "House Blend Coffee";
}

double HouseBlend::cost()
{
    return 0.89;
}

DarkRoast::DarkRoast()
{
    m_description = "Dark Roast Coffee";
}

double DarkRoast::cost()
{
    return 0.99;
}

Decaf::Decaf()
{
    m_description = "Decaf Coffee";
}

double Decaf::cost()
{
    return 1.05;
}

Mocha::Mocha(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

Mocha::~Mocha()
{
    delete m_pBeverage;
}

string Mocha::getDescription()
{
    return m_pBeverage->getDescription() + " + Mocha";
}

double Mocha::cost()
{
    return 0.20 + m_pBeverage->cost();
}

Milk::Milk(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

Milk::~Milk()
{
    delete m_pBeverage;
}

string Milk::getDescription()
{
    return m_pBeverage->getDescription() + " + Milk";
}

double Milk::cost()
{
    return 0.10 + m_pBeverage->cost();
}

Soy::Soy(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

Soy::~Soy()
{
    delete m_pBeverage;
}

string Soy::getDescription()
{
    return m_pBeverage->getDescription() + " + Soy";
}

double Soy::cost()
{
    return 0.15 + m_pBeverage->cost();
}

Whip::Whip(Beverage* pBeverage)
{
    m_pBeverage = pBeverage;
}

Whip::~Whip()
{
    delete m_pBeverage;
}

string Whip::getDescription()
{
    return m_pBeverage->getDescription() + " + Whip";
}

double Whip::cost()
{
    return 0.10 + m_pBeverage->cost();
}
int main()
{
    Beverage* pBeverage = new Espresso();
    cout << pBeverage->getDescription() << " $" << pBeverage->cost() << endl;

    Beverage* pBeverage2 = new DarkRoast();
    pBeverage2 = new Mocha(pBeverage2);
    pBeverage2 = new Mocha(pBeverage2);
    pBeverage2 = new Whip(pBeverage2);
    cout << pBeverage2->getDescription() << " $" << pBeverage2->cost() << endl;

    Beverage* pBeverage3 = new HouseBlend();
    pBeverage3 = new Soy(pBeverage3);
    pBeverage3 = new Mocha(pBeverage3);
    pBeverage3 = new Whip(pBeverage3);
    cout << pBeverage3->getDescription() << " $" << pBeverage3->cost() << endl;
    delete pBeverage;
    delete pBeverage2;
    delete pBeverage3;
    return 0;
}
复制代码




运行后结果如下:

Espresso $1.99
Dark Roast Coffee + Mocha + Mocha + Whip $1.49
House Blend Coffee + Soy + Mocha + Whip $1.34

 

参考图书:《Head First 设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值