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

概念

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

应用场景

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

优点

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

示例

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

示例一

代码实现

#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 方法。

运行结果

在这里插入图片描述

示例二

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

代码实现

#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;  
}

运行结果

在这里插入图片描述

示例三

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

实现代码

#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;  
}

运行结果

在这里插入图片描述

总结

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

相关推荐

  1. 设计模式装饰模式 -- C++】

    2023-12-19 06:44:03       53 阅读
  2. C++设计模式装饰模式

    2023-12-19 06:44:03       23 阅读
  3. 装饰设计模式

    2023-12-19 06:44:03       51 阅读
  4. 设计模式装饰模式

    2023-12-19 06:44:03       66 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-19 06:44:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-19 06:44:03       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-19 06:44:03       82 阅读
  4. Python语言-面向对象

    2023-12-19 06:44:03       91 阅读

热门阅读

  1. 【Leetcode】计算器

    2023-12-19 06:44:03       65 阅读
  2. 数据的输入输出(C++)

    2023-12-19 06:44:03       58 阅读
  3. Docker (Dockerfile运行jar) -day 05

    2023-12-19 06:44:03       64 阅读
  4. .net web API的文件传输(上传和下载)客户端winform

    2023-12-19 06:44:03       48 阅读
  5. 【Node】npm使用手册

    2023-12-19 06:44:03       60 阅读
  6. 文件相关工具类Utils(WORD,PDF,PNG)

    2023-12-19 06:44:03       53 阅读
  7. 第六章--- 实现微服务:匹配系统(下)

    2023-12-19 06:44:03       40 阅读
  8. 在iframe怎么把外面的dialog关掉

    2023-12-19 06:44:03       57 阅读