装饰器模式

49 阅读2分钟
classDiagram
Component <.. ConcreteComponent
Component <.. Decorator
Decorator <-- ConcreteDecoratorA
Decorator <-- ConcreteDecoratorB
class Component{
<<abstract>>
+Operation() string
}
class ConcreteComponent {
+  Operation()
}
class Decorator{
   - m_component:Component*
    +Operation()
    
}
class ConcreteDecoratorA{
    +  Operation()
    + AddedBehavior()
}
class ConcreteDecoratorB{
    +  Operation()
    + AddedBehavior()
}

来源: 代码

#include <bits/stdc++.h>

/*
 *@brief 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
 * 场景:
 * 优点:
 * (1)装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用;
 * (2)通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果;
 * (3)装饰器模式完全遵守开闭原则.
 * 缺点:
 * 装饰模式会增加许多子类,过度使用会增加程序得复杂性。
 */

//基础组件接口定义了可以被装饰器修改的操作
class Component
{
public:
    virtual ~Component() {}
    virtual std::string Operation() const = 0;
};

//具体组件提供了操作的默认实现,这些类在程序中可能会有几个变体
class ConcreteComponent : public Component
{
public:
    std::string Operation() const override
    {
        return "ConcreteComponent";
    }
};

//装饰器基类和其他组件遵循相同的接口。这个类的主要目的是为所有的具体装饰器定义封装接口。
//封装的默认实现代码中可能会包含一个保存被封装组件的成员变量,并且负责对齐进行初始化
class Decorator : public Component
{

protected:
    Component *component_;

public:
    Decorator(Component *component) : component_(component) {}

    //装饰器会将所有的工作分派给被封装的组件
    std::string Operation() const override
    {
        return this->component_->Operation();
    }
};

//具体装饰器必须在被封装对象上调用方法,不过也可以自行在结果中添加一些内容。
class ConcreteDecoratorA : public Decorator
{

    //装饰器可以调用父类的是实现,来替代直接调用组件方法。
public:
    ConcreteDecoratorA(Component *component) : Decorator(component) {}
    std::string Operation() const override
    {
        return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
    }
};

//装饰器可以在调用封装的组件对象的方法前后执行自己的方法
class ConcreteDecoratorB : public Decorator
{
public:
    ConcreteDecoratorB(Component *component) : Decorator(component)
    {
    }

    std::string Operation() const override
    {
        return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
    }
};
//客户端代码可以使用组件接口来操作所有的具体对象。这种方式可以使客户端和具体的实现类脱耦
void ClientCode(Component *component)
{
    // ...
    std::cout << "RESULT: " << component->Operation();
    // ...
}

int main()
{

    Component *simple = new ConcreteComponent;
    std::cout << "Client: I've got a simple component:\n";
    // RESULT: ConcreteComponent
    ClientCode(simple);
    std::cout << "\n\n";

    Component *decorator1 = new ConcreteDecoratorA(simple);
    // RESULT: ConcreteDecoratorA(ConcreteComponent
    ClientCode(decorator1);

    Component *decorator2 = new ConcreteDecoratorB(decorator1);
    // RESULT: ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent))
    ClientCode(decorator2);
    std::cout << "\n";

    delete simple;
    delete decorator1;
    delete decorator2;

    return 0;
}