C++设计模式——装饰器模式

装饰器设计模式

概念

装饰器设计模式,是C++设计模式中的一种。它是一种结构型设计模式,允许向现有对象动态地添加新功能,同时又不改变其结构。这种模式是通过创建一个包装对象来实现的,也就是说,实际对象被包装在装饰器类的实例中。装饰器类实现了与实际对象相同的接口,并且可以添加额外的行为。

应用场景

装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。在不改变原有类结构的基础上,扩展新的功能。

优点

降低代码之间的耦合性,提高了灵活性,具有更好的扩展性。

示例

下面是三个简单的C++实现装饰器模式的示例,仅供理解该设计模式。

示例一

代码实现

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

// 接口
class Component {
public:
    virtual void operation() = 0;
};

// 具体组件
class ConcreteComponent : public Component {
public:
    virtual void operation() {
        cout << "具体对象的操作" << endl;
    }
};

// 装饰器
class Decorator : public Component {
protected:
    Component* component;
public:
    void setComponent(Component* component) {
        this->component = component;
    }
    virtual void operation() {
        if (component != nullptr) {
            component->operation();
        }
    }
};

// 具体装饰器
class ConcreteDecoratorA : public Decorator {
public:
    virtual void operation() {
        Decorator::operation(); // 调用父类的operation
        addedBehavior();
    }
    void addedBehavior() {
        cout << "为具体构件A扩展的操作" << endl;
    }
};

class ConcreteDecoratorB : public Decorator {
public:
    virtual void operation() {
        Decorator::operation(); // 调用父类的operation
        addedBehavior();
    }
    void addedBehavior() {
        cout << "为具体构件B扩展的操作" << endl;
    }
};

int main() {
    Component* component = new ConcreteComponent();
    Decorator* decorator1 = new ConcreteDecoratorA();
    Decorator* decorator2 = new ConcreteDecoratorB();

    decorator1->setComponent(component);
    decorator2->setComponent(decorator1);
    decorator2->operation();

    delete decorator2;
    delete decorator1;
    delete component;

    return 0;
}

在这个示例中,Component 是接口,定义了操作的抽象方法。ConcreteComponent 是具体的对象。Decorator 是装饰器类,继承自 Component,并包含一个指向 Component 对象的指针。ConcreteDecoratorA 和 ConcreteDecoratorB 是具体的装饰器类,继承自 Decorator,并在 operation 方法中扩展了额外的行为。

在 main 函数中,我们创建了一个具体的对象 component,然后通过 ConcreteDecoratorA 和 ConcreteDecoratorB 对其进行装饰,最终调用 decorator2 的 operation 方法。

运行结果

示例二

使用装饰器模式实现一个计算图形面积的程序,并添加日志记录功能。

代码实现

cpp 复制代码
#include <iostream>  
#include <string>  
  
// 定义一个接口类  
class Shape {  
public:  
    virtual double getArea() = 0;  
};  
  
// 实现接口类的具体类  
class Rectangle : public Shape {  
private:  
    double width;  
    double height;  
public:  
    Rectangle(double w, double h) : width(w), height(h) {}  
    double getArea() override {  
        std::cout << "Rectangle::getArea() - calculating area..." << std::endl;  
        return width * height;  
    }  
};  
  
// 实现一个装饰器类,用于给具体类添加额外的功能  
class ShapeDecorator : public Shape {  
protected:  
    Shape* decoratedShape; // 保存一个指向被装饰对象的指针  
public:  
    ShapeDecorator(Shape* shape) : decoratedShape(shape) {}  
    double getArea() override {  
        return decoratedShape->getArea(); // 调用被装饰对象的操作  
    }  
};  
  
// 具体的装饰器类,添加日志记录功能  
class LoggingShapeDecorator : public ShapeDecorator {  
private:  
    std::string message;  
public:  
    LoggingShapeDecorator(Shape* shape, std::string msg) : ShapeDecorator(shape), message(msg) {}  
    double getArea() override {  
        std::cout << message << " - starting calculation..." << std::endl;  
        double result = decoratedShape->getArea(); // 调用被装饰对象的操作  
        std::cout << message << " - calculation complete." << std::endl;  
        return result;  
    }  
};  
  
int main() {  
    Shape* rectangle = new Rectangle(5, 10); // 创建一个具体对象  
    Shape* loggingRectangle = new LoggingShapeDecorator(rectangle, "Rectangle::getArea()"); // 创建一个被装饰的对象,并添加日志记录功能  
    std::cout << "Area: " << rectangle->getArea() << std::endl; // 输出 "Rectangle::getArea() - calculating area..." 和 "Area: 50"  
    std::cout << "Area (with logging): " << loggingRectangle->getArea() << std::endl; // 输出 "Rectangle::getArea() - starting calculation...", "Rectangle::getArea() - calculating area...", "Rectangle::getArea() - calculation complete." 和 "Area (with logging): 50"  
    delete rectangle; // 释放内存  
    delete loggingRectangle; // 释放内存  
    return 0;  
}

运行结果

示例三

使用装饰器模式编写一个绘图功能,并模拟添加一些额外的功能。

实现代码

cpp 复制代码
#include <iostream>  
#include <string>  
  
// 定义一个接口类  
class Shape {  
public:  
    virtual void draw() = 0;  
};  
  
// 实现接口类的具体类  
class Rectangle : public Shape {  
public:  
    void draw() override {  
        std::cout << "Rectangle::draw()" << std::endl;  
    }  
};  
  
// 实现一个装饰器类,用于给具体类添加额外的功能  
class ShapeDecorator : public Shape {  
protected:  
    Shape* decoratedShape; // 保存一个指向被装饰对象的指针  
public:  
    ShapeDecorator(Shape* shape) : decoratedShape(shape) {}  
    void draw() override {  
        decoratedShape->draw(); // 调用被装饰对象的操作  
    }  
};  
  
// 具体的装饰器类,添加新的功能  
class RedShapeDecorator : public ShapeDecorator {  
public:  
    RedShapeDecorator(Shape* shape) : ShapeDecorator(shape) {}  
    void draw() override {  
        decoratedShape->draw(); // 调用被装饰对象的操作  
        std::cout << "RedShapeDecorator::draw() - draw red border" << std::endl;  
    }  
};  
  
int main() {  
    Shape* rectangle = new Rectangle(); // 创建一个具体对象  
    Shape* redRectangle = new RedShapeDecorator(new Rectangle()); // 创建一个被装饰的对象  
    rectangle->draw(); // 输出 "Rectangle::draw()"  
    redRectangle->draw(); // 输出 "Rectangle::draw()" 和 "RedShapeDecorator::draw() - draw red border"  
    delete rectangle; // 释放内存  
    delete redRectangle; // 释放内存  
    return 0;  
}

运行结果

总结

装饰器设计模式其本质上还是使用多态的原理,提供了一种可扩展功能的设计模式。

相关推荐
木向几秒前
leetcode22:括号问题
开发语言·c++·leetcode
筑基.8 分钟前
basic_ios及其衍生库(附 GCC libstdc++源代码)
开发语言·c++
yuyanjingtao21 分钟前
CCF-GESP 等级考试 2023年12月认证C++三级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
越甲八千2 小时前
重温设计模式--代理、中介者、适配器模式的异同
设计模式·适配器模式
王老师青少年编程2 小时前
gesp(二级)(12)洛谷:B3955:[GESP202403 二级] 小杨的日字矩阵
c++·算法·矩阵·gesp·csp·信奥赛
OTWOL3 小时前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
QQ同步助手3 小时前
C++ 指针进阶:动态内存与复杂应用
开发语言·c++
信徒_3 小时前
常用设计模式
java·单例模式·设计模式
qq_433554543 小时前
C++ 面向对象编程:递增重载
开发语言·c++·算法
易码智能3 小时前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts