Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++设计模式——Decorator装饰器模式

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

作者头像
Coder-ZZ
发布于 2024-06-18 07:30:08
发布于 2024-06-18 07:30:08
20000
代码可运行
举报
文章被收录于专栏:C/C++进阶专栏C/C++进阶专栏
运行总次数:0
代码可运行

一,装饰器模式简介

装饰器模式是一种结构型设计模式, 它允许在不改变现有对象的情况下,动态地将功能添加到对象中。

装饰器模式是通过创建具有新行为的对象来实现的,这些对象将原始对象进行了包装。

装饰器模式遵循开放/关闭原则,允许开发者在不修改现有代码的情况下添加新的装饰器。

日常开发中常用的装饰器属于类装饰器,通过继承父类来实现。

二,装饰器模式的结构

1.抽象组件(Component):被装饰的对象,声明了对外的统一接口。

2.具体组件(ConcreteComponent):包含抽象组件接口的具体代码实现。

3.抽象装饰器(Decorator):包含对抽象组件的指针或引用,并定义了与抽象组件一致的接口。

4.具体装饰器(ConcreteDecorator):包含抽象装饰器接口的具体代码实现,并且可以在调用对外接口之前或之后添加额外的行为。

对应UML类图:

拿生活中举例:某硬核产品的可拆卸装饰

三,装饰器模式的工作步骤

1.创建抽象组件类,定义抽象组件的对外接口,将核心功能声明在该接口中。

2.创建具体组件类,继承抽象组件类,实现抽象组件类的接口。

3.创建抽象装饰器类,继承抽象组件类,实现抽象组件类的接口,并持有一个抽象组件对象的引用。

4.创建具体装饰器类,继承抽象装饰器类,在实现核心接口之后,添加额外的接口函数。

5.在客户端中使用装饰器包装抽象组件,并调用它们的方法。

四,装饰器模式代码样例

Demo1:

为了简化理解,暂时不带具体装饰器ConcreteDecorator,直接在Decorator中添加额外功能。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>

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

class ConcreteComponent : public Component {
public:
    void operation() override {
        std::cout << "From ConcreteComponent." << std::endl;
    }
};

class Decorator : public Component {
public:
    Decorator(Component& component):component_(component){}
    void operation() override {
        std::cout << "from Decorator." << std::endl;
        component_.operation();
    }

private:
    Component& component_;
};

int main() {
    ConcreteComponent concreteComponent;
    Decorator decoratedComponent(concreteComponent);
    decoratedComponent.operation();
    return 0;
}

运行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from Decorator.
From ConcreteComponent.

五,装饰器模式的应用场景

组件扩展:在大型项目中,随着业务的增加,必定要添加新的功能,装饰器此时可以避免修改原有的基础组件。

API增强:当提供API给第三方进行调用时,装饰器可以用于添加额外的功能,比如日志记录、安全校验等,而调用者无需知道具体的细节。

权限管理:装饰器可以用来控制对原有的特定接口的访问权限。

缓存机制:在网络请求或数据库查询等操作中,装饰器可以用来添加额外的缓存、重试、超时处理等功能。

六,装饰器模式的优缺点

装饰器模式的优点:

1.可以动态地添加或删除对象的功能,无需修改原有的代码。

2.不影响现有对象的结构,符合开闭原则。

3.可以灵活地扩展原有对象的功能。

4.可以使用多个装饰器对象来组合多种功能。

5.使得代码可以根据需要轻松地添加或移除功能。

装饰器模式的缺点:

1.使系统中增加额外的类变量。

2.装饰器对象与原始对象之间的关系过于复杂,降低代码可读性。

七,代码实战

Demo1: 自助冰淇淋制作机

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <string>

using namespace std;

// Component
class IceCream {
public:
    virtual string getDescription() const = 0;
    virtual double cost() const = 0;
};

// Concrete Component
class VanillaIceCream : public IceCream {
public:
    string getDescription() const override
    {
        return "Vanilla Ice Cream";
    }

    double cost() const override { return 160.0; }
};

// Decorator
class Decorator : public IceCream {
protected:
    IceCream* iceCream;

public:
    Decorator(IceCream* ic)
        : iceCream(ic)
    {
    }

    string getDescription() const override
    {
        return iceCream->getDescription();
    }

    double cost() const override
    {
        return iceCream->cost();
    }
};

// Concrete Decorator - adds chocolate topping.
class ChocolateDecorator : public Decorator {
public:
    ChocolateDecorator(IceCream* ic)
        : Decorator(ic)
    {
    }

    string getDescription() const override
    {
        return iceCream->getDescription()
            + " with Chocolate";
    }

    double cost() const override
    {
        return iceCream->cost() + 100.0;
    }
};

// Concrete Decorator - adds caramel topping.
class CaramelDecorator : public Decorator {
public:
    CaramelDecorator(IceCream* ic)
        : Decorator(ic)
    {
    }

    string getDescription() const override
    {
        return iceCream->getDescription() + " with Caramel";
    }

    double cost() const override
    {
        return iceCream->cost() + 150.0;
    }
};

int main()
{
    // Create a vanilla ice cream
    IceCream* vanillaIceCream = new VanillaIceCream();
    cout << "Order: " << vanillaIceCream->getDescription()
        << ", Cost: Rs." << vanillaIceCream->cost()
        << endl;

    // Wrap it with ChocolateDecorator
    IceCream* chocolateIceCream
        = new ChocolateDecorator(vanillaIceCream);
    cout << "Order: " << chocolateIceCream->getDescription()
        << ", Cost: Rs." << chocolateIceCream->cost()
        << endl;

    // Wrap it with CaramelDecorator
    IceCream* caramelIceCream
        = new CaramelDecorator(chocolateIceCream);
    cout << "Order: " << caramelIceCream->getDescription()
        << ", Cost: Rs." << caramelIceCream->cost()
        << endl;

    delete vanillaIceCream;
    delete chocolateIceCream;
    delete caramelIceCream;

    return 0;
}

运行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Order: Vanilla Ice Cream, Cost: Rs.160
Order: Vanilla Ice Cream with Chocolate, Cost: Rs.260
Order: Vanilla Ice Cream with Chocolate with Caramel, Cost: Rs.410

Demo2: 模拟的绘图组件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
using namespace std;

// Component
class Widget
{
public:
    virtual void draw() = 0;
};

// Concrete Component
class TextField : public Widget
{
    int width, height;
public:
    TextField(int w, int h)
    {
        width = w;
        height = h;
    }
    void draw()
    {
      cout << "TextField: " << width << "," << height;
    }
};

// Decorator
class Decorator : public Widget  
{
    Widget* wid;
public:
    Decorator(Widget* w)
    {
        wid = w;
    }
    void draw()
    {
        wid->draw();
    }
};

// Concrete Decorator
class BorderDecorator : public Decorator
{
public:
    BorderDecorator(Widget* w): Decorator(w){}
    void draw()
    {
        //基础功能
        Decorator::draw();
        //扩展功能
        cout << "\n BorderDecorator" ;
    }
};

// Concrete Decorator
class ScrollDecorator : public Decorator
{
public:
    ScrollDecorator(Widget* w): Decorator(w){}
    /*virtual*/
    void draw()
    {
        //基础功能
        Decorator::draw();
        //扩展功能
        cout << "\n ScrollDecorator";
    }
};
int main()
{
    Widget* aWidget = new BorderDecorator(
     new ScrollDecorator(new TextField(80, 24)));
    aWidget->draw();
}

运行结果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
TextField: 80,24
ScrollDecorator
BorderDecorator

八,参考阅读

https://www.pentalog.com/blog/design-patterns/decorator-design-pattern/

https://www.geeksforgeeks.org/introduction-to-decorator-pattern-in-c-design-patterns/

https://sourcemaking.com/design_patterns/decorator/cpp/2

https://sourcemaking.com/design_patterns/decorator

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员与背包客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
23种设计模式,装饰器模式实战
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。
小马哥学JAVA
2024/04/06
1810
一文搞懂设计模式—装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向现有对象添加新功能而不改变其结构。装饰器模式通过创建包装对象(装饰器)来动态地扩展对象的行为,是继承的替代方案之一。
BookSea
2024/02/29
6360
一文搞懂设计模式—装饰器模式
【面试题精讲】javaIO设计模式之装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将新功能添加到对象中。它通过创建一个包装类来实现,在不改变原有对象的基础上,为对象添加额外的行为。
程序员朱永胜
2023/10/22
2610
GoF 23种经典的设计模式——装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
Andromeda
2024/01/21
700
「聊设计模式」之装饰器模式(Decorator)
🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!
bug菌
2023/11/06
3951
「聊设计模式」之装饰器模式(Decorator)
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
用户11531739
2025/03/14
380
设计模式(6)-装饰器(认识程序中的装饰器)
之前已经看过装饰器模式,但是感觉不是很清晰,但是有一种情况下出的代码,一定是装饰器。 Widget* aWidget = new BorderDecorator( new BorderDecorator( new ScrollDecorator( new TextField( 80, 24 )))); 可以看到,层层嵌套,每个类都可以按照一定的顺序嵌套多次。 比如将顺序改为如下: Widget* bWidget = new ScrollDecorator( new BorderDecorat
cloudskyme
2018/03/20
8170
设计模式(6)-装饰器(认识程序中的装饰器)
装饰器模式
装饰模式是一种结构型设计模式,允许动态地向对象添加新功能,而不会影响其他对象。装饰模式通过使用一系列装饰类,将额外的行为或责任以层叠的方式附加到对象上。
码事漫谈
2024/12/20
670
装饰器模式
设计模式 (三)——装饰者模式(Decorator,结构型)
使用设计模式可以提高代码的可复用性、可扩充性和可维护性。装饰者模式( Pattern)属于结构型模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。它是通过创建一个包装对象,通过包装对象来包裹真实的对象,以达到装饰目的。
恋喵大鲤鱼
2018/08/03
8090
设计模式 (三)——装饰者模式(Decorator,结构型)
【Java设计模式系列】装饰器模式(Decorator Pattern)
装饰模式以对用户透明的方式动态给一个对象附加功能。用户不会觉得对象在装饰前、后有何不同。装饰模式可在无需创造更多子类情况下,扩展对象的功能。
JavaEdge
2021/10/18
3550
结合案例深入解析装饰者模式
允许向一个现有的对象添加新的功能。同时又不改变其结构,它是作为现有的类的一个包装。
李红
2019/06/14
3650
结合案例深入解析装饰者模式
设计模式之装饰者模式(Decorator Pattern)问题提出引出装饰者模式定义装饰者模式实现装饰者模式总结与分析
装饰者模式可以做到在不修改任何底层代码的情况下,给对象增加的新的方法。 首先,我们通过对一个现实问题的模拟分析,了解什么是装饰者模式以及装饰者模式的作用。
desperate633
2018/08/22
5200
设计模式之装饰者模式(Decorator Pattern)问题提出引出装饰者模式定义装饰者模式实现装饰者模式总结与分析
跟着GPT学设计模式之装饰者模式
装饰者模式是一种结构型设计模式,它允许你在不修改已有对象的情况下,动态地向对象添加额外的功能。装饰者模式通过包装原始对象来扩展其功能,并提供了一种灵活的方式来组合多个装饰器。装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。
codetrend
2024/03/30
1040
Java设计模式:深入装饰器模式的三种写法(六)
Java中的装饰器模式是一种结构型设计模式,它允许你在不修改现有类的情况下,动态地将新功能添加到对象上。装饰器模式通过创建一个包装了原始对象的装饰器类来实现这一点。装饰器类与原始类具有相同的接口,因此它们可以互换使用。
公众号:码到三十五
2024/03/19
3630
Java设计模式:深入装饰器模式的三种写法(六)
设计模式---装饰者模式
装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
大忽悠爱学习
2021/11/15
3250
设计模式(八)装饰器模式Decorator(结构型)
上面的类图看起来并不怎么坏,下面让我们再增加一些特性。表单验证阶段,你希望能够指出一个表单控制是否合法。你为非法控制使用的代码又一次继承其它组件,因此又需要产生大量的子类:
黄规速
2022/04/14
3880
设计模式(八)装饰器模式Decorator(结构型)
装饰器模式Decorator Pattern-23种常用设计模式快速入门教程
装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变原有对象的基础上,动态地给对象添加新的职责和行为。 该模式的核心思想是以递归的方式,通过将对象包装在装饰器对象中,来不断添加新的行为和职责。装饰器模式的结构包括以下角色:
jack.yang
2025/04/05
420
Java设计模式-装饰器模式 理论代码相结合
上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。在我们自己行业就是这个东西得加需求啦
宁在春
2022/10/31
4120
Java设计模式-装饰器模式 理论代码相结合
Java设计模式之装饰器模式
在面向对象设计中,经常会遇到需要在不改变现有类结构的情况下,动态地为对象添加新的功能的需求。这时候,装饰器模式就派上了用场。
刺槐儿
2024/01/24
4600
设计模式之装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变现有对象的结构的情况下,动态地给对象增加一些额外的功能。装饰器模式通过创建一个包装对象(即装饰器)来包裹真实对象,并在保持真实对象的接口不变的前提下,为其提供额外的功能。装饰器模式可以在运行时根据需要选择不同的装饰器来组合和修改对象的行为。
wayn
2023/09/12
2330
设计模式之装饰器模式
推荐阅读
相关推荐
23种设计模式,装饰器模式实战
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验