设计模式学习之——装饰者模式

news/2024/12/15 16:35:05/

装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地向一个现有的对象添加新的行为,同时又不改变其结构。

一、定义与特点

  • 定义:装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。

  • 特点

    • 结构型模式:装饰者模式关注于对象的组合以及如何通过组合来实现新的功能。
    • 动态扩展:通过装饰者模式,可以在不修改原有类代码的情况下,动态地向对象添加新的行为。
    • 透明性:装饰后的对象仍然可以被当作原有类型的对象来使用,客户端代码不需要知道对象是否被装饰过。

二、关键角色与职责

  • Component(抽象构件)

    • 定义一个接口或抽象类,声明了在具体构件中实现的业务方法。
    • 它是具体构件和抽象装饰类的共同父类,引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
  • ConcreteComponent(具体构件)

    • 实现了Component接口或抽象类的具体类,定义了具体的构件对象。
    • 实现了在Component中声明的方法,装饰器可以给它增加额外的职责(方法)。
  • Decorator(抽象装饰类)

    • 继承自Component接口或抽象类,用于给具体构件增加职责。
    • 维护一个指向Component对象的引用,通过该引用可以调用装饰之前构件对象的方法。
    • 需要在子类中实现具体的装饰行为。
  • ConcreteDecorator(具体装饰类)

    • 继承自Decorator抽象类,负责向构件添加新的职责。
    • 每一个具体装饰类都定义了一些新的行为,可以调用在Decorator中定义的方法,并可以增加新的方法用以扩充对象的行为。

三、运行机制

  • 创建具体构件对象:首先创建一个具体构件对象,这是需要被装饰的原始对象。
  • 创建装饰器对象:接着创建一个或多个装饰器对象,通过构造函数将具体构件对象传入装饰器对象。
  • 调用方法:当调用装饰后对象的方法时,装饰器对象会先调用其所持有的具体构件对象的方法,然后再执行自己定义的额外行为。

四、适用场景

  • 功能扩展:需要为一个类扩展功能,为其添加额外的职责。
  • 动态添加行为:需要在运行时动态地向对象添加新的行为,而不需要修改其类定义。
  • 避免子类爆炸:通过装饰者模式可以避免通过继承来扩展功能所导致的子类数量过多的问题。

五、优缺点

  • 优点

    • 灵活性:提供了比继承更加灵活的功能扩展方式。
    • 可扩展性:可以通过组合不同的装饰器来创建具有不同行为的新对象。
    • 透明性:装饰后的对象仍然可以被当作原有类型的对象来使用。
  • 缺点

    • 复杂性:会产生很多的小对象,增加了系统的复杂性。
    • 排错困难:对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。

六、代码示例

示例一:Java中的IO流

以Java中的IO流为例,InputStream和OutputStream是最基本的抽象构件,而各种FilterInputStream和FilterOutputStream就是具体的装饰器,它们可以实现各种不同的IO流处理功能,如缓冲、压缩、加密等。

// 抽象构件
InputStream input = new FileInputStream("example.txt");// 具体装饰器(缓冲流)
BufferedInputStream bufferedInput = new BufferedInputStream(input);// 再次装饰(数据输入流)
DataInputStream dataInput = new DataInputStream(bufferedInput);// 使用装饰后的对象读取数据
while (dataInput.available() != 0) {System.out.print((char) dataInput.readByte());
}
dataInput.close();

在这个例子中,FileInputStream是具体构件,BufferedInputStreamDataInputStream是具体装饰器,它们依次对输入流进行了缓冲和数据处理功能的装饰。

示例二:咖啡制作 

在咖啡制作系统中,一杯咖啡可以有多种调料(如糖、奶、奶油等)。通过装饰器模式,可以动态地为咖啡添加不同的调料,而不需要创建大量的子类来表示不同调料组合的咖啡

   interface Coffee {double cost();}class SimpleCoffee implements Coffee {@Overridepublic double cost() {return 1.0;}}abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}}class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return coffee.cost() + 0.5;}}

综上所述,装饰者模式是一种强大且灵活的设计模式,它允许我们在不修改原有类代码的情况下动态地向对象添加新的行为。然而,在使用时也需要注意其可能带来的系统复杂性和排错困难等问题。


http://www.ppmy.cn/news/1555343.html

相关文章

《Vue进阶教程》第十课:其它函数

往期内容: 《Vue零基础入门教程》合集(完结) 《Vue进阶教程》第一课:什么是组合式API 《Vue进阶教程》第二课:为什么提出组合式API 《Vue进阶教程》第三课:Vue响应式原理 《Vue进阶教程》第四课&#…

opencv-python的简单练习

题目1.读取一张彩色图像并将其转换为灰度图。 import cv2 # 读取图片文件 img cv2.imread(./1.png)# 将原图灰度化 img_gray cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# 输出图片 cv2.imshow(img,img) cv2.imshow(img_g,img_gray) # 进行阻塞 cv2.waitKey(0) 题目2:…

【Axure视频教程】中继器表格——打开指定页面

今天教大家在Axure制作中继器表格--打开指定页面的原型模板,鼠标点击表格里员工所在行的查看简历按钮,就可以跳转至该员工对应的简历页面。这个原型模板是用中继器制作的,所以使用也很简单,只需要在中继器表格里填写对应内容&…

Android 异形屏设备设置沉浸式界面

Android 异形屏设备设置沉浸式界面 问题 由于业务需要,应用需要配置沉浸式界面,但设置全屏时,会遇到异形屏采用传统的全屏设置模式无效问题。 解决方案 Android P版本提供参数layoutInDisplayCutoutMode供实现沉浸式设置。layoutInDispl…

c语言数据结构与算法--简单实现线性表(顺序表+链表)的插入与删除

老规矩,点赞评论收藏关注!!! 目录 线性表 其特点是: 算法实现: 运行结果展示 链表 插入元素: 删除元素: 算法实现 运行结果 线性表是由n个数据元素组成的有限序列,每个元…

双重AEB:将基于规则的方法与多模态大型语言模型相结合,以实现有效的紧急制动(202410)

Dual-AEB: Synergizing Rule-Based and Multimodal Large Language Models for Effective Emergency Braking 双重AEB:将基于规则的方法与多模态大型语言模型相结合,以实现有效的紧急制动 Abstract Automatic Emergency Braking (AEB) systems are a c…

PyTorch 梯度计算详解:以 detach 示例为例

PyTorch 梯度计算详解:以 detach 示例为例 在深度学习中,梯度计算是训练模型的核心步骤,而 PyTorch 通过自动微分(autograd)模块实现了高效的梯度求解。本文将通过一个实际代码示例,详细讲解 PyTorch 的梯…

测试脚本并发多进程:pytest-xdist用法

参考:https://www.cnblogs.com/poloyy/p/12694861.html pytest-xdist详解: https://www.cnblogs.com/poloyy/p/14708825.html 总 https://www.cnblogs.com/poloyy/category/1690628.html