Java设计模式 十 装饰模式 (Decorator Pattern)

devtools/2025/1/25 2:52:44/

装饰模式 (Decorator Pattern)

装饰模式是一种结构型设计模式,它的作用是动态地为对象添加额外的职责,而不修改其代码结构。装饰模式通过创建装饰类,将核心功能与附加功能分离,使得代码更灵活,更具扩展性。


1. 装饰模式的组成

装饰模式包含以下角色:

  • Component(抽象组件): 定义对象的通用接口,可以动态地为该接口添加职责。
  • ConcreteComponent(具体组件): 组件的具体实现,是最基础的对象。
  • Decorator(装饰器): 持有一个 Component 的引用,并定义一个与 Component 一致的接口。
  • ConcreteDecorator(具体装饰器): 实现具体的装饰功能,同时调用组件的核心功能。

2. 装饰模式的优点

  1. 功能扩展灵活: 可以动态地为对象添加功能,而不需要修改原有类。
  2. 遵循开闭原则: 增加功能时,无需修改已有代码,只需增加新的装饰器类。
  3. 细粒度控制: 每个装饰器只负责一个特定的功能,职责单一。

3. 装饰模式的缺点

  1. 增加复杂性: 每个装饰器都是一个新的类,可能导致类数量增加。
  2. 调试困难: 如果多个装饰器嵌套使用,可能会导致调试和排错复杂化。

4. 装饰模式的实现

场景示例:给文本添加装饰功能

需求: 假设我们有一个文本处理组件,支持基本的文本输出功能。现在需要为它动态添加功能,比如加粗、斜体、添加颜色等。


1) 定义抽象组件

抽象组件定义通用接口,表示所有文本处理组件的公共行为。

java">// 抽象组件
public interface Text {String render(); // 渲染文本
}

2) 实现具体组件

具体组件实现基本的文本渲染功能。

java">// 具体组件
public class PlainText implements Text {private String content;public PlainText(String content) {this.content = content;}@Overridepublic String render() {return content;}
}

3) 定义装饰器

装饰器类持有一个 Text 的引用,负责为组件动态添加功能。

java">// 抽象装饰器
public abstract class TextDecorator implements Text {protected Text text;public TextDecorator(Text text) {this.text = text;}@Overridepublic String render() {return text.render();}
}

4) 实现具体装饰器

具体装饰器负责添加不同的功能,例如加粗和斜体。

java">// 加粗装饰器
public class BoldText extends TextDecorator {public BoldText(Text text) {super(text);}@Overridepublic String render() {return "<b>" + super.render() + "</b>";}
}// 斜体装饰器
public class ItalicText extends TextDecorator {public ItalicText(Text text) {super(text);}@Overridepublic String render() {return "<i>" + super.render() + "</i>";}
}// 颜色装饰器
public class ColoredText extends TextDecorator {private String color;public ColoredText(Text text, String color) {super(text);this.color = color;}@Overridepublic String render() {return "<span style='color:" + color + "'>" + super.render() + "</span>";}
}

5) 客户端代码

客户端可以自由组合不同的装饰器来扩展功能。

java">public class Client {public static void main(String[] args) {// 基础文本Text text = new PlainText("Hello, World!");// 添加加粗功能Text boldText = new BoldText(text);// 添加斜体功能Text italicText = new ItalicText(boldText);// 添加颜色功能Text coloredText = new ColoredText(italicText, "red");// 渲染最终文本System.out.println(coloredText.render());}
}

运行结果:
<span style='color:red'><i><b>Hello, World!</b></i></span>

最终输出的文本是带有颜色、加粗和斜体的 HTML 格式。


5. 装饰模式的应用场景

  1. 动态扩展功能:
    需要为对象动态添加功能,并且可能在运行时组合多种功能。

  2. 代替继承:
    使用装饰模式可以避免通过继承实现功能扩展,减少类的数量。

  3. 需要根据不同需求组合功能:
    比如 GUI 系统中的组件,可能需要动态添加滚动条、边框、阴影等功能。


6. Java 中的典型应用

  1. java.io 包中的装饰器模式

    • InputStreamOutputStream 类的子类:
      • BufferedInputStream
      • DataInputStream
      • FilterInputStream
    • 通过装饰器动态扩展流的功能:
      java">InputStream input = new FileInputStream("file.txt");
      InputStream bufferedInput = new BufferedInputStream(input);
      
  2. Java Swing

    • Java Swing 的组件可以动态添加边框等效果:
      java">JTextField textField = new JTextField();
      textField.setBorder(BorderFactory.createLineBorder(Color.BLACK));
      

7. 装饰模式与其他模式的比较

模式主要用途与装饰模式的区别
代理模式控制对象的访问代理模式不改变对象的功能,装饰模式增加新功能。
适配器模式接口不兼容的对象协同工作适配器模式主要解决接口问题,装饰模式动态增强功能。
桥接模式分离抽象和实现桥接模式关注结构设计,装饰模式关注动态增强功能。

8. 总结

装饰模式是一种灵活、优雅的设计模式,它通过组合的方式动态为对象添加功能,而不修改原有代码。装饰模式遵循开闭原则,是功能扩展需求中的理想选择。

在实际开发中,装饰模式广泛应用于流处理、GUI 系统以及其他需要动态功能扩展的场景。它是一种高效且值得掌握的设计模式


http://www.ppmy.cn/devtools/153289.html

相关文章

2024 开源社年度报告:拥抱开源新生活

2024 年&#xff0c;开源社步入了 10 周年。10 这个数字不论在十进制还是二进制中都代表着一次进位&#xff0c;而「进化」也成为了开源社 2024 的关键词。 在这一年&#xff0c;我们迭代了开源社的使命愿景 —— 10 年前我们写下开源社的愿景&#xff1a;立足中国、贡献全球&a…

python操作mysql

前言 在 Python3 中&#xff0c;我们可以使用mysqlclient或者pymysql三方库来接入 MySQL 数据库并实现数据持久化操作。二者的用法完全相同&#xff0c;只是导入的模块名不一样。我们推荐大家使用纯 Python 的三方库pymysql&#xff0c;因为它更容易安装成功。下面我们仍然以之…

C#/.NET/.NET Core技术前沿周刊 | 第 22 期(2025年1.13-1.19)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿、推荐…

golang 编程规范 - Effective Go 中文

原文&#xff1a;https://makeoptim.com/golang/effective-go 介绍 示例 格式化&#xff08;Formatting&#xff09; 缩进行的长度括号 注释&#xff08;Commentary&#xff09; 命名&#xff08;Names&#xff09; 包名获取器接口命名驼峰命名 分号&#xff08;Semicolons&am…

2024年IT运维行业年度回顾

2024年&#xff0c;IT运维行业在技术、市场、政策和各行业应用等方面都取得了显著进展。以下是对2024年IT运维行业的详细回顾&#xff1a; 一、市场规模与增长 1.全球市场&#xff1a; - 全球IT运维服务行业市场规模总体保持稳定增长。 2.中国市场&#xff1a; - 中国IT运维…

FastExcel导入Excel详细步骤

1.添加maven坐标 <dependency><groupId>cn.idev.excel</groupId><artifactId>fastexcel</artifactId><version>1.0.0</version> <!-- 请确保使用最新版本 --></dependency>2.创建实体类和监听器 import com.alibaba.ex…

【嵌入式】总结——Linux驱动开发(三)

鸽了半年&#xff0c;几乎全忘了&#xff0c;幸亏前面还有两篇总结。出于快速体验嵌入式linux的目的&#xff0c;本篇与前两篇一样&#xff0c;重点在于使用、快速体验&#xff0c;uboot、linux、根文件系统不作深入理解&#xff0c;能用就行。 重新梳理一下脉络&#xff0c;本…

chrome小插件:长图片等分切割

前置条件&#xff1a; 安装有chrome谷歌浏览器的电脑 使用步骤&#xff1a; 1.打开chrome扩展插件 2.点击管理扩展程序 3.加载已解压的扩展程序 4.选择对应文件夹 5.成功后会出现一个扩展小程序 6.点击对应小程序 7.选择图片进行切割&#xff0c;切割完成后会自动保存 代码…