当前位置: 首页 > news >正文

java设计模式六、装饰器模式

什么是装饰器模式

装饰器模式是一种结构型设计模式,它允许在不改变对象原有结构的情况下,动态地给对象添加额外的功能。这种模式通过创建包装对象来实现功能的扩展,是继承的一个替代方案。

核心思想:在保持接口不变的前提下,对原有功能进行扩展和增强。

装饰器模式的结构

在这里插入图片描述

装饰器模式的优势

  1. 灵活性:比继承更灵活,可以在运行时动态添加功能
  2. 符合开闭原则:对扩展开放,对修改关闭
  3. 避免类爆炸:不需要为每个功能组合创建子类
  4. 职责分离:不同的装饰器负责不同的功能

缓冲输入流装饰器

java

package com.YA33.design.decorator;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;/*** 缓冲输入流装饰器 - 为文件输入流添加缓冲功能* 作者:YA33*/
public class BufferedInputStream extends InputStream {private final FileInputStream fileInputStream;// 缓冲区,存储从文件读取的数据private final byte[] buffer = new byte[8192]; // 8KB缓冲区// 当前读取位置指针private int position = -1;// 缓冲区中有效数据的容量private int capacity = -1;public BufferedInputStream(FileInputStream fileInputStream) {this.fileInputStream = fileInputStream;}@Overridepublic int read() throws IOException {/*** 读取逻辑:* 1. 如果缓冲区有数据,直接从缓冲区读取* 2. 如果缓冲区为空,先刷新缓冲区* 3. 如果刷新后仍无数据,返回-1表示结束*/if (bufferCanRead()) {return readFromBuffer();}refreshBuffer();if (!bufferCanRead()) {return -1;}return readFromBuffer();}/*** 从缓冲区读取一个字节*/private int readFromBuffer() {// 与上0xff去掉符号位,将byte转为无符号int// 因为byte的范围是-128~127,而我们需要0~255的范围return buffer[position++] & 0xff;}/*** 刷新缓冲区,从文件流中读取新数据*/private void refreshBuffer() throws IOException {capacity = this.fileInputStream.read(buffer);position = 0;}/*** 检查缓冲区是否可读*/private boolean bufferCanRead() {// 容量为-1表示未初始化if (-1 == capacity) return false;// 位置等于容量表示已读完if (capacity == position) return false;return true;}@Overridepublic void close() throws IOException {fileInputStream.close();super.close();}
}

历史记录集合装饰器

java

package com.YA33.design.decorator;import java.util.*;/*** 历史记录集合装饰器 - 记录被删除的元素历史* YA*/
public class HistorySet<E> implements Set<E> {// 记录被删除的元素private final List<E> removeHistory = new ArrayList<>();// 被装饰的原始集合private final Set<E> delegate;public HistorySet(Set<E> delegateSet) {this.delegate = delegateSet;}@Overridepublic boolean remove(Object o) {/*** 增强的删除方法:* - 执行原始删除操作* - 如果删除成功,记录到删除历史中*/if (delegate.remove(o)) {removeHistory.add((E) o);return true;}return false;}/*** 获取删除历史记录*/public List<E> getRemoveHistory() {return new ArrayList<>(removeHistory);}/*** 清空删除历史*/public void clearHistory() {removeHistory.clear();}// 以下方法直接委托给原始集合@Overridepublic int size() {return delegate.size();}@Overridepublic boolean isEmpty() {return delegate.isEmpty();}@Overridepublic boolean contains(Object o) {return delegate.contains(o);}@Overridepublic Iterator<E> iterator() {return delegate.iterator();}@Overridepublic Object[] toArray() {return delegate.toArray();}@Overridepublic <T> T[] toArray(T[] a) {return delegate.toArray(a);}@Overridepublic boolean add(E e) {return delegate.add(e);}@Overridepublic boolean containsAll(Collection<?> c) {return delegate.containsAll(c);}@Overridepublic boolean addAll(Collection<? extends E> c) {return delegate.addAll(c);}@Overridepublic boolean retainAll(Collection<?> c) {return delegate.retainAll(c);}@Overridepublic boolean removeAll(Collection<?> c) {boolean modified = false;for (Object item : c) {modified |= remove(item);}return modified;}@Overridepublic void clear() {// 清空时记录所有元素到删除历史removeHistory.addAll(delegate);delegate.clear();}@Overridepublic String toString() {return "当前集合: " + delegate.toString() + "\n删除历史: " + removeHistory;}
}

日志输出流装饰器

java

package com.YA33.design.decorator;import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;/*** 日志输出流装饰器 - 为输出流添加日志记录功能* 作者:YA33*/
public class LoggingOutputStream extends OutputStream {private final OutputStream delegate;private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public LoggingOutputStream(OutputStream delegate) {this.delegate = delegate;}@Overridepublic void write(int b) throws IOException {log("写入单个字节: " + b);delegate.write(b);}@Overridepublic void write(byte[] b) throws IOException {log("写入字节数组,长度: " + b.length);delegate.write(b);}@Overridepublic void write(byte[] b, int off, int len) throws IOException {log(String.format("写入字节数组,偏移量: %d, 长度: %d", off, len));delegate.write(b, off, len);}@Overridepublic void flush() throws IOException {log("刷新输出流");delegate.flush();}@Overridepublic void close() throws IOException {log("关闭输出流");delegate.close();}/*** 记录日志信息*/private void log(String message) {String timestamp = dateFormat.format(new Date());System.out.println("[" + timestamp + "] " + message);}
}

测试代码

java

package com.YA33.design.decorator;import java.io.*;
import java.time.Instant;
import java.util.*;public class DecoratorPatternDemo {public static void main(String[] args) {System.out.println("=== 装饰器模式演示 ===\n");// 测试历史记录集合testHistorySet();// 测试缓冲输入流testBufferedInputStream();// 测试日志输出流testLoggingOutputStream();}/*** 测试历史记录集合装饰器*/public static void testHistorySet() {System.out.println("1. 历史记录集合测试:");Set<String> historySet = new HistorySet<>(new HashSet<>());// 添加元素historySet.add("Apple");historySet.add("Banana");historySet.add("Orange");historySet.add("Grape");System.out.println("初始集合: " + historySet);// 删除元素historySet.remove("Banana");historySet.remove("Grape");System.out.println("删除后集合: " + historySet);// 获取删除历史HistorySet<String> typedSet = (HistorySet<String>) historySet;System.out.println("删除历史: " + typedSet.getRemoveHistory());System.out.println();}/*** 测试缓冲输入流性能*/public static void testBufferedInputStream() {System.out.println("2. 缓冲输入流性能测试:");try {// 创建一个测试文件File testFile = createTestFile();// 测试普通文件流long startTime = Instant.now().toEpochMilli();readWithFileInputStream(testFile);long endTime = Instant.now().toEpochMilli();System.out.println("普通文件流耗时: " + (endTime - startTime) + "ms");// 测试缓冲文件流startTime = Instant.now().toEpochMilli();readWithBufferedInputStream(testFile);endTime = Instant.now().toEpochMilli();System.out.println("缓冲文件流耗时: " + (endTime - startTime) + "ms");// 清理测试文件testFile.delete();} catch (IOException e) {System.err.println("文件操作错误: " + e.getMessage());}System.out.println();}/*** 测试日志输出流*/public static void testLoggingOutputStream() {System.out.println("3. 日志输出流测试:");try {ByteArrayOutputStream byteArrayOutput = new ByteArrayOutputStream();LoggingOutputStream loggingOutput = new LoggingOutputStream(byteArrayOutput);loggingOutput.write("Hello, Decorator Pattern!".getBytes());loggingOutput.write(65); // 写入字符'A'loggingOutput.flush();loggingOutput.close();System.out.println("输出内容: " + byteArrayOutput.toString());} catch (IOException e) {System.err.println("输出流错误: " + e.getMessage());}System.out.println();}/*** 创建测试文件*/private static File createTestFile() throws IOException {File file = new File("test_data.txt");try (FileOutputStream fos = new FileOutputStream(file)) {// 写入1MB测试数据byte[] data = new byte[1024]; // 1KBArrays.fill(data, (byte) 'A');for (int i = 0; i < 1024; i++) { // 写入1024次,共1MBfos.write(data);}}return file;}private static void readWithFileInputStream(File file) throws IOException {try (FileInputStream fis = new FileInputStream(file)) {while (fis.read() != -1) {// 逐个字节读取}}}private static void readWithBufferedInputStream(File file) throws IOException {try (InputStream bis = new BufferedInputStream(new FileInputStream(file))) {while (bis.read() != -1) {// 通过缓冲流读取}}}
}

装饰器模式的应用场景

  1. IO流处理:Java中的BufferedInputStream、DataInputStream等
  2. 集合框架:Collections.synchronizedCollection()等工具方法
  3. Web开发:HTTP请求/响应的过滤器链
  4. GUI开发:为可视化组件添加滚动、边框等功能
  5. 中间件:为服务调用添加日志、监控、重试等功能

总结

装饰器模式通过组合的方式,在不修改原有代码的基础上为对象动态添加功能,体现了"组合优于继承"的设计原则。在实际开发中,合理使用装饰器模式可以让代码更加灵活、可扩展,同时保持良好的结构清晰度。

通过本文的三个示例,我们可以看到装饰器模式在不同场景下的应用:缓冲功能、历史记录功能和日志功能。每种装饰器都专注于单一职责,通过组合可以创造出功能丰富的对象,这正是装饰器模式的魅力所在。

http://www.dtcms.com/a/515523.html

相关文章:

  • 微信小程序隐藏滚动条多种方法教程
  • AWS DMS实现MySQL到Redshift的CDC增量数据复制方案
  • 王者重名生成查询抖音快手微信小程序看广告流量主开源
  • 旅游网站建设1000字软文范例800字
  • 网站搜索引擎友好性最近三天发生的重要新闻
  • Flink的checkpoint interval与mini-batch什么区别?
  • CADSoftTools发布两款重要更新:CAD VCL Multiplatform 16.2 与 CAD .NET 16全新发布
  • 【个人成长笔记】在本地Windows系统中如何正确使用adb pull命令,把Linux系统中的文件或文件夹复制到本地中(亲测有效)
  • 触摸未来2025-10-22:语序之困
  • 【滑动窗口与双指针】【定长滑窗】—1456. 定长子串中元音的最大数目
  • Flink 实验性特性把“已预分区”的 DataStream 重新解释为 KeyedStream
  • ADB -> 常用文件操作的组合命令
  • 网格系统网站济南网约车公司
  • 社区网站的推广方案手机写wordpress博客
  • 原子性、可见性和指令重排问题的根源
  • 什么是测试覆盖率?如何衡量?
  • 《宝可梦传说Z-A》下载 整合龙神Ryuinx、eden模拟器附金手指和存档 安卓手机PC版
  • 自动驾驶---基于安全走廊的端到端
  • 2025主流AI标书工具推荐,“闭眼选”高效生成投标文件
  • (22)100天python从入门到拿捏《【网络爬虫】网络基础与HTTP协议》
  • iis6建设网站叶梓 wordpress 主题
  • 【C#】获取电脑网卡MAC地址
  • ​2025网络安全前景与学习路线:抓住数字时代的安全机遇
  • Linux小课堂: SSH 服务部署与客户端连接实战详解
  • 好看网站手机版南开做网站公司
  • 七日 Go 的自学笔记 (一)
  • Node.js 接入淘宝 API 实战:构建商品信息实时同步服务
  • Node.js SQL数据库:MySQL/PostgreSQL集成
  • 虚拟化网络连接与虚拟机嵌套
  • 无锡企业制作网站网站建设项目的费用做什么科目