设计模式:装饰器模式

2023-09-17 16:17:22

装饰器模式是一种结构型设计模式,用于在不改变原有对象的基础上,动态地给对象添加额外的功能。装饰器模式通过将对象包装在一个装饰器对象中,然后逐层地添加装饰器,实现对对象的功能进行增强或修改。装饰器模式可以在运行时动态地添加、删除或修改对象的行为,而无需修改原始对象的结构。这种模式常用于需要灵活地扩展对象功能的场景,同时遵循开闭原则,即对扩展开放,对修改关闭。

组件

装饰器模式包含以下组件:

  1. 抽象构件(Component):定义了被装饰对象和装饰器对象的共同接口,可以是抽象类或接口。
  2. 具体构件(ConcreteComponent):实现了抽象构件接口,是被装饰的原始对象。
  3. 抽象装饰器(Decorator):继承或实现了抽象构件接口,并持有一个抽象构件的引用,它可以动态地添加、删除或修改具体构件的行为。
  4. 具体装饰器(ConcreteDecorator):实现了抽象装饰器接口,负责给具体构件对象添加额外的功能。
    通过组合这些组件,装饰器模式可以实现对对象的透明装饰,即在不改变原有对象结构的情况下,动态地给对象添加新的行为或修改原有行为。
    请注意,以下对话将继续使用英语进行,除非特定的语言名称在下文中提及。

代码实现

interface Component {
    void operation();
}
 // 具体构件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("执行具体构件的操作");
    }
}
 // 抽象装饰器
abstract class Decorator implements Component {
    protected Component component;
     public Decorator(Component component) {
        this.component = component;
    }
     @Override
    public void operation() {
        component.operation();
    }
}
 // 具体装饰器
class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
     @Override
    public void operation() {
        super.operation();
        System.out.println("添加额外的功能A");
    }
}
 class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }
     @Override
    public void operation() {
        super.operation();
        System.out.println("添加额外的功能B");
    }
}
 // 示例代码
public class Main {
    public static void main(String[] args) {
        // 创建具体构件对象
        Component component = new ConcreteComponent();
        // 创建具体装饰器对象,并传入具体构件对象
        Decorator decoratorA = new ConcreteDecoratorA(component);
        Decorator decoratorB = new ConcreteDecoratorB(decoratorA);
        // 执行操作
        decoratorB.operation();
    }
}

在上述示例中,我们定义了抽象构件接口(Component),并实现了具体构件(ConcreteComponent)。然后,我们定义了抽象装饰器(Decorator),并创建了具体装饰器A(ConcreteDecoratorA)和具体装饰器B(ConcreteDecoratorB)。这些装饰器可以动态地给具体构件对象添加额外的功能。在主函数中,我们创建了具体构件对象,并使用装饰器A和装饰器B进行装饰,最后执行了装饰后的操作。

源码中使用

在Spring源码中,装饰器模式是一种常见的设计模式之一。装饰器模式通过动态地将责任附加到对象上,来扩展其功能。在Spring框架中,装饰器模式常用于AOP(面向切面编程)的实现。

Spring中的AOP模块使用装饰器模式来实现横切关注点的功能,例如事务管理、日志记录和安全性等。通过使用装饰器模式,Spring能够在不修改原始对象的情况下,动态地添加额外的行为。

在Spring源码中,装饰器模式的实现可以在AOP相关的类和接口中找到,例如ProxyFactory、Advice、Advisor和Interceptor等。这些类和接口提供了一种灵活的方式,可以通过装饰器模式来包装和增强目标对象的功能。

优缺点

优点:

  1. 装饰器模式遵循开放封闭原则,允许在不修改现有代码的情况下扩展对象的功能。
  2. 可以通过组合多个装饰器类,实现对对象功能的灵活组合和配置。
  3. 装饰器模式避免了使用继承来扩展对象行为所带来的静态特性,使得代码更灵活、可扩展和可维护。

缺点:

  1. 过多使用装饰器模式可能导致类的数量增加,增加了代码复杂性和理解难度。
  2. 装饰器模式可能会引入许多细粒度的对象,增加了系统的复杂性和内存消耗。
  3. 当装饰器类过多或过于复杂时,可能会导致调试和排错变得困难。

总结

装饰器模式是一种灵活且可扩展的设计模式,适用于需要动态地为对象增加功能的场景。它提供了一种比继承更加灵活的方式来扩展对象的行为,但过度使用装饰器模式可能会导致代码复杂性增加。因此,在使用装饰器模式时,需要权衡其优点和缺点,确保合理使用。

更多推荐

【数字人】1、SadTalker | 使用语音驱动单张图片合成视频(CVPR2023)

SadTalker:使用一张图片和一段语音来生成口型和头、面部视频论文:SadTalker:LearningRealistic3DMotionCoefficientsforStylizedAudio-DrivenSingleImageTalkingFaceAnimation代码:https://github.com/W

计算机视觉与深度学习-卷积神经网络-卷积&图像去噪&边缘提取-卷积与边缘提取-[北邮鲁鹏]

目录标题参考学习链接什么是图像边缘?为什么研究边缘?有哪些边缘种类?表面法向不连续深度不连续表面颜色不连续光照不连续如何检测边缘?图像求导图像梯度图像梯度的方向图像梯度的模噪声的影响噪声影响带来的问题解决办法(先平滑处理)高斯核去噪高斯一阶偏导核高斯核vs高斯一阶偏导核边缘检测目标Canny边缘检测器高斯一阶偏导核卷积

如何从主机环境演变到云原生开发模式?

时代在发展,我们的知识,开发工具,以及相应的环境也随之进步,我们总是会趋向于向好的一面发展,期望我们自身能够更加优秀,更加高效,以及能够给周围的人带来更多的价值那么在我们平日开发过程中,你们的开发模式,以及开发环境是如何演变的呢?如下是我近一两年经历的变化,希望能给你们带来一些思考和收获混沌之初还是主机环境起初在接触g

Redis淘汰策略-架构案例2020(三十六)

上篇案例回顾:解释器,管道过滤,隐式调用优缺点?解释器则是独立的语法规则,可以通过解释器来解析,可扩展性很高,灵活性强。管道过滤则是侧重于数据的输入和输出,上一个模块的数据输出是下一个模块的输入,连接件事管道,过滤则是构件。隐式调用则强调触发和异步,多个构件会注册到一个模块里,当模块改变的时候,构件都会接收到消息从而跟

以酒为媒、以酒载道,五粮液携手首届“金熊猫奖”,讲好中国白酒故事

执笔|尼奥编辑|萧萧这是一次光影艺术与白酒酿造的和美之约,也是中国文化与世界多元文明的交融时刻,在影视与美酒的碰撞瞬间,共同擘画“美美与共,天下大同”的文明图景。9月19-20日,以“多彩文明·荣耀光影”为主题的首届“金熊猫奖”评选活动在成都举行。五粮液作为首届“金熊猫奖”全球战略合作伙伴亮相,深度融入金熊猫之夜、金熊

【C++】vector中的常见函数和使用

前言感觉vector在目前阶段很常用,就总结记录一些vector的用法方便自己忘记的时候查找因为是自用,所以我直接放代码了,只说明如何使用,以及一些小的注意点,对于函数具体实现过程,在这篇文章中,不做过多说明当然,我也给出了一些使用例子,供大家参考本文参考:C++vector操作代码#include<iostream>

报错处理:Error: Redis server is running but Redis CLI cannot connect

嗨,读者朋友们!今天我来跟大家分享一个我在运维过程中遇到的一个关于Linux上运行Redis服务时的报错及解决方法。报错信息如下:Error:RedisserverisrunningbutRedisCLIcannotconnect这个报错信息表明Redis服务器已经运行,但Redis命令行界面(CLI)无法连接。针对这

Python itertools教程(python中的迭代器与组合迭代器)

当谈到在Python中优雅地处理迭代任务时,itertools库是一个不可或缺的工具。这个强大的库提供了一系列用于创建、操作和合并迭代器的函数,能够让你的代码更加紧凑、高效,并且更易于阅读和维护。无论是解决排列组合问题、处理无限序列,还是简化循环结构,itertools都能够成为你的得力助手。Pythonitertoo

为什么建议项目经理尽快考CSPM?告诉你答案

2021年10月,中共中央、国务院发布的《国家标准化发展纲要》明确提出构建多层次从业人员培养培训体系,开展专业人才培养培训和国家质量基础设施综合教育。建立健全人才的职业能力评价和激励机制。由中国标准化协会(CAS)组织开展的项目管理专业人员能力评价等级证书(CSPM)应运而生。关于为什么要提前报考CSPM项目管理专业人

【Web3】DAO相关的基础知识

这里写目录标题DAO的基础概念为什么需要DAO?DAO的种类DAO的运作方式知名DAO的介绍BanklessDAOSeeDAODAO的生态全景图分类治理框架DAO的工具DAO众筹平台介绍-JuiceBoxDAO投票治理介绍-SnapshotDAO贡献&激励-POAPDAO信息管理-NotionDAO与传统组织的比较DA

css知识学习系列(4)-每天10个知识点

目录1.**CSS中的“box-sizing”属性与“border”属性有什么关系?**2.**在CSS中,如何使用“calc()”函数进行计算?有什么使用技巧?**3.**在CSS中,如何使用“@import”引入外部样式表?有哪些注意事项?**4.**Flexbox和Grid布局在实践中哪个更常用?为什么?**5.

热文推荐