2023-6-26-第八式装饰器模式

简介: 2023-6-26-第八式装饰器模式

😉一、基础概念

装饰器模式是一种结构型设计模式,它通过动态的将责任附加到对象上来扩展对象的功能。换句话说,它提供了一种不通过子类化就能扩展对象功能的方式。装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。

在装饰器模式中,有一个基本的对象,称之为组件(component),它定义了一个共同的接口,可以被具体的组件或装饰器所实现。装饰器(decorator)会对组件进行包装,从而给组件增加新的功能。装饰器也实现了组件的接口,所以它们可以互相嵌套和组合,从而形成一个功能更加丰富的对象。

在代码实现上,装饰器模式使用一个装饰器类对组件进行包装,并将其传递给另一个装饰器,直到所有的装饰器都被执行完毕。这个过程中,每个装饰器都可以通过调用组件的方法来增加、修改或删除组件的行为。最终,得到的对象拥有了所有的装饰器所提供的功能。

所以,装饰器模式的优点在于:可以动态地给对象增加新的功能,而不需要修改原有的代码。缺点在于:装饰器的嵌套可能会导致复杂的代码结构,而且不正确地使用装饰器将使代码难以维护。


🐱‍🐉二、装饰器模式实现

首先,我们定义一个基础组件类Component和一个具体组件类ConcreteComponent:

class Component {
public:
    virtual void operation() = 0;
};
class ConcreteComponent : public Component {
public:
    virtual void operation() override {
        std::cout << "ConcreteComponent operation.\n";
    }
};

然后我们定义一个装饰器类Decorator,它继承自Component并持有一个指向Component对象的指针,以便在装饰过程中调用原对象的方法。Decorator还定义了一个名为addBehavior()的纯虚函数,用于在装饰过程中添加新功能。

class Decorator : public Component {
public:
    Decorator(Component* component) : component_(component) {}
    virtual void operation() override {
        if (component_)
            component_->operation();
    }
    virtual void addBehavior() = 0;
protected:
    Component* component_;
};

接下来,我们定义两个具体装饰器类ConcreteDecoratorA和ConcreteDecoratorB,它们继承自Decorator并重写了operation()和addBehavior()方法,以实现自定义的装饰功能。

class ConcreteDecoratorA : public Decorator {
public:
    ConcreteDecoratorA(Component* component) : Decorator(component) {}
    virtual void operation() override {
        Decorator::operation();
        std::cout << "ConcreteDecoratorA operation.\n";
    }
    virtual void addBehavior() override {
        std::cout << "ConcreteDecoratorA added behavior.\n";
    }
};
class ConcreteDecoratorB : public Decorator {
public:
    ConcreteDecoratorB(Component* component) : Decorator(component) {}
    virtual void operation() override {
        Decorator::operation();
        std::cout << "ConcreteDecoratorB operation.\n";
    }
    virtual void addBehavior() override {
        std::cout << "ConcreteDecoratorB added behavior.\n";
    }
};

最后,我们可以在客户端代码中使用这些类来实现装饰器模式。我们首先创建一个具体组件对象ConcreteComponent,然后将其传递给ConcreteDecoratorA对象,并调用addBehavior()方法来添加新功能。随后,我们将ConcreteDecoratorA对象传递给ConcreteDecoratorB对象再次添加新功能,并调用operation()方法,输出所有添加的功能。

int main() {
    Component* component = new ConcreteComponent();
    ConcreteDecoratorA* decoratorA = new ConcreteDecoratorA(component);
    decoratorA->addBehavior();
    ConcreteDecoratorB* decoratorB = new ConcreteDecoratorB(decoratorA);
    decoratorB->addBehavior();
    decoratorB->operation();
    delete decoratorB;
    delete decoratorA;
    delete component;
    return 0;
}

输出结果如下:

ConcreteComponent operation.
ConcreteDecoratorA operation.
ConcreteDecoratorA added behavior.
ConcreteDecoratorB operation.
ConcreteDecoratorB added behavior.

🎉三、模块之间的关系

在装饰器模式中,有四个关键角色:抽象组件、具体组件、抽象装饰器和具体装饰器。

抽象组件是定义对象的接口,可以是抽象类或接口,具体组件是实现抽象组件的类,具体装饰器是实现抽象装饰器的类,抽象装饰器是定义装饰器的接口,可以是抽象类或接口。

这四个角色之间的关系是:抽象组件可以包含具体组件,抽象装饰器可以包含抽象组件,具体装饰器可以包含抽象装饰器,具体装饰器也可以包含具体组件,形成一个以抽象装饰器为根节点的装饰器链。通过这个链,每一个装饰器都可以动态地为组件添加新的功能。

当客户端想要使用某个具体组件时,可以使用抽象装饰器来对其进行装饰,不需要知道具体组件的实现细节,这样可以实现组件与装饰器的解耦。


🐱‍🚀四、注意事项

使用桥接模式时需要注意以下事项:

  1. 抽象部分与实现部分分离。在使用桥接模式时,需要将抽象部分与实现部分分离开来,确保它们可以独立进行变化。这有助于提高系统的灵活性和可扩展性。
  2. 接口细化。在设计抽象部分和实现部分的接口时,需要尽可能细化,以确保它们的功能可以清晰地描述。
  3. 优先使用对象组合。在实现桥接模式时,需要优先使用对象组合,而不是继承。如果使用继承,可能会引发类层次结构的剧增,导致系统难以维护。
  4. 不要滥用桥接模式。桥接模式并不是一种万能模式,使用时需要根据具体情况来决定是否使用。如果使用不当,可能会导致系统的复杂度增加,反而降低系统的可维护性和可扩展性。
  5. 安全性考虑。在使用桥接模式时,需要考虑安全性的问题。特别是在桥接的两端,需要确保数据的完整性和安全性。

🎂五、使用场景

桥接模式适用于以下场景:

1.抽象和实现部分具有平行的等级结构,需要在运行时动态组合它们。桥接模式能够使抽象和实现部分各自独立变化,且能够在运行时动态组合它们,因此能够很好地适应这种场景。

2.要求不同的抽象子类可以与不同的实现子类进行组合。桥接模式能够通过抽象角色和实现角色的分离,实现不同的抽象子类可以与不同的实现子类进行组合,从而可以灵活地处理不同的组合情况。

3.一个类存在多个独立变化的维度,需要支持动态组合。桥接模式能够将各个维度的变化分离,使得每个维度的变化可以独立地扩展,从而可以非常灵活地支持多维度的动态组合。

综上所述,桥接模式适用于具有多个独立变化维度的场景,能够很好地支持这种复杂度。但需要注意的是,若使用不当,桥接模式也可能带来额外的复杂度。因此,应在设计时慎重考虑是否真正需要使用桥接模式。


🍳参考文献

🧊文章总结

提示:这里对文章进行总结:

  本文讲了关于桥接模式的知识。


目录
相关文章
|
安全 数据安全/隐私保护
【氚云】部门数据操作权限设置
部门数据操作权限设置
1403 0
【氚云】部门数据操作权限设置
|
10月前
|
存储 缓存 Java
Java数组全解析:一维、多维与内存模型
本文深入解析Java数组的内存布局与操作技巧,涵盖一维及多维数组的声明、初始化、内存模型,以及数组常见陷阱和性能优化。通过图文结合的方式帮助开发者彻底理解数组本质,并提供Arrays工具类的实用方法与面试高频问题解析,助你掌握数组核心知识,避免常见错误。
|
5月前
|
存储 弹性计算 关系型数据库
2026阿里云服务器地域选择指南:节点特性与适配策略解析
阿里云服务器在全球布局 29 个地域、92 个可用区,覆盖中国内地、海外及中国香港等关键区域,不同地域在网络延迟、产品兼容性、合规要求上差异显著。地域选择并非单纯以 “速度快” 为唯一标准,需结合用户分布、业务架构、合规需求等多维度综合判断。本文结合官方技术规范与实测数据,详解地域选择的核心逻辑、节点特性及典型场景适配方案,为业务部署提供客观参考。
|
移动开发 小程序 JavaScript
小程序与快应用:中国移动互联网的渐进式革命——卓伊凡的技术演进观
小程序与快应用:中国移动互联网的渐进式革命——卓伊凡的技术演进观
495 12
小程序与快应用:中国移动互联网的渐进式革命——卓伊凡的技术演进观
|
6月前
|
前端开发 算法 Java
2025最新Java面试题
涵盖Java基础、算法、Web开发、主流框架(Spring/SpringBoot/SpringCloud)、数据库及常用组件,提供前端、人事、Agent等多类面试题,含《中州养老》《云岚到家》等实战项目解析,持续更新面试录音与复盘资料。
|
12月前
|
网络虚拟化
配置OptionC方式跨域VPN示例
本文介绍了跨域BGP/MPLS IP VPN的配置方法。公司总部(CE1)与分部(CE2)分别通过不同运营商AS10和AS20接入,同属vpn1。配置思路包括:1) 配置IGP协议实现骨干网互通;2) 配置MPLS基本能力和LDP建立LSP;3) 配置VPN实例并绑定接口;4) 建立EBGP对等体交换路由;5) 在ASBR-PE上发布带标签的路由;6) 配置MP-EBGP对等体关系。操作步骤涵盖IP地址配置、MPLS骨干网互通、VPN实例接入及路由验证,确保跨域通信正常。
|
11月前
|
人工智能 运维 数据可视化
分享小伙伴私信推荐的5款小工具
本文推荐了五款实用的免费工具,涵盖任务栏优化、代码编辑、在线AI工具、云端协作及思维可视化。包括TranslucentTB、Sublime Text、3171.CN、石墨文档与知犀思维导图,适用于各类办公与学习场景,提升效率与协作体验。
372 0
|
存储 弹性计算 测试技术
10分钟私有部署QwQ-32B模型,像购买Ecs实例一样快捷
虽然阿里云提供了基于 IaaS 部署 QwQ-32B 模型的方式,但传统的基于IaaS的部署方式需要用户自行配置环境、安装依赖、优化硬件资源,并解决复杂的网络与存储问题,整个流程不仅耗时耗力,还容易因操作失误导致各种不可预见的问题。 因此,阿里云计算巢提供了基于ECS镜像与VLLM的大模型一键部署方案,通过ECS镜像打包标准环境,通过Ros模版实现云资源与大模型的一键部署,用户无需关心模型部署运行的标准环境与底层云资源编排,10分钟即可部署使用QwQ-32B模型,15分钟即可部署使用Deepseek-R1-70B模型。
|
JSON 自然语言处理 API
合合信息TextIn大模型加速器2.0发布:智能图表解析测评
随着人工智能技术的飞速发展,大规模语言模型(LLM)在自然语言处理、图像识别、语音合成等领域的应用日益广泛。然而,大模型的计算复杂度和资源消耗问题也日益凸显。为了解决这一问题,合合信息TextIn推出了大模型加速器2.0,旨在提升大模型的训练和推理效率,降低计算成本,完成智能问答与对话式交互,深度概括与定位等。本文将对合合信息TextIn大模型加速器2.0进行详细测评,重点关注其在智能图表解析任务中的表现。
1200 0
合合信息TextIn大模型加速器2.0发布:智能图表解析测评
|
机器学习/深度学习 人工智能 数据可视化
无需微调!扩散模型新突破:Attentive Eraser高效稳定移除目标物体
最近,扩散模型在生成模型领域异军突起,凭借其独特的生成机制在图像生成方面大放异彩,尤其在处理高维复杂数据时优势明显。然而,尽管扩散模型在图像生成任务中表现优异,但在图像目标移除任务中仍然面临诸多挑战。现有方法在移除前景目标后,可能会留下残影或伪影,难以实现与背景的自然融合。
552 9

热门文章

最新文章