装饰者模式

概念

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

装饰者与和被装饰者必须有相同的超类, 这是相当关键的地方, 在此模式中, 我们利用继承达到"类型匹配", 而不是利用继承来获得"行为"

适用场景

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。扩展一个复杂类的时候,很可能会暴露与添加的职责无关的细节。

缺点:
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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值