实战:基于 java-design-patterns 的模块化数据处理指南)
示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载管道模式Pipeline Pattern是一种行为型设计模式它将数据处理拆分为一串有序的独立阶段stage前一阶段的输出作为后一阶段的输入从而把复杂的数据处理流程变成一条可读、可测、可扩展的流水线。本文以 java-design-patterns 仓库中的 pipeline 模块 为蓝本结合 西班牙语文档 与源码实现完整讲解该模式的意图、代码骨架、运行结果、适用场景与取舍帮助读者掌握如何用 Java 泛型与函数式接口构建自己的处理管道。模式概述为什么需要 Pipeline意图与核心思想管道模式的意图是允许数据通过一系列有序的阶段被处理初始输入进入第一级处理后的输出依次被后续阶段消费。每一个已实现的任务对应管道中的一个阶段stage。你可以把管道想象成工厂里的装配线装配线上的每个零部件都是分阶段组装起来的半成品从一个装配工位传递到下一个工位最终产出的顺序与输入进入的顺序保持一致。用一句话概括——管道模式就是一条装配线部分结果从一个阶段流向另一个阶段。维基百科对软件工程中 pipeline 的定义同样精准在软件工程中管道由一串处理元素进程、线程、协程、函数等组成每个元素的输出是下一个元素的输入其命名类比于物理管道。与本仓库中其他模式的关系在 java-design-patterns 仓库中管道模式被归类为Behavioral行为型模式核心标签包括Decoupling解耦并涉及 API design、Data processing、Extensibility、Functional decomposition 等特性。它与 Chain of Responsibility责任链、Decorator装饰器、Composite组合 密切相关但各有侧重后文相关模式辨析会详细展开。模式结构Handler 与 Pipeline 的职责划分整个模式的骨架非常精简核心只有两个角色Handler阶段处理器定义了每个处理阶段的统一契约——接受某类型输入产出某类型输出Pipeline管道负责收集各阶段 Handler并以函数复合的方式把它们串接起来对外提供一次性的执行入口。对应到仓库源码即 Handler.java 与 Pipeline.java 两个文件。下面逐段剖析。阶段契约Handler 接口interface HandlerI, O { O process(I input); }这是整个模式的基石I是该阶段接收的输入类型O是该阶段产出的输出类型。任何想要成为管道中一环的类只需实现process方法即可完全不需要关心管道中其他阶段的存在——这正是解耦的体现。管道本体Pipeline 类的两种类型参数class PipelineI, O { private final HandlerI, O currentHandler; Pipeline(HandlerI, O currentHandler) { this.currentHandler currentHandler; } K PipelineI, K addHandler(HandlerO, K newHandler) { return new Pipeline(input - newHandler.process(currentHandler.process(input))); } O execute(I input) { return currentHandler.process(input); } }从源码Pipeline.java可以看到三个关键设计类型参数语义PipelineI, O中的I表示整条管道第一个阶段的输入类型O表示最后一个阶段的输出类型。无论管道内部串联了多少个 Handler对外暴露的永远是整体输入 → 整体输出。addHandler的巧妙之处addHandler(HandlerO, K newHandler)要求新阶段恰好接受当前管道输出类型O返回新类型K随后通过 lambdainput - newHandler.process(currentHandler.process(input))把旧管道与新阶段复合成一条新的管道PipelineI, K。这本质上是函数组合function composition只是被封装成了流畅的链式调用。注意它返回的是新对象因此每次添加阶段都会产生新的 Pipeline 实例原管道保持不变——这赋予了管道不可变immutable的特性避免并发或复用时的状态污染。execute即最终触发把输入交给最内层即最初那级Handler由内部嵌套的调用链依次完成全流程处理。类型安全的链式保障addHandler的泛型签名保证了编译期类型安全如果某个阶段的输出类型与下一阶段的输入类型不匹配代码根本无法通过编译。这一点在 App.java 的注释中有明确说明——在管道的任何阶段Handler 都可以返回任意类型的数据只要它满足下一阶段 Handler 的输入要求。实战示例字符串处理三阶段管道本仓库的示例以字符串过滤为场景管道中串联了 3 个具体 Handler全部位于com.iluwatar.pipeline包下阶段实现类输入 → 输出职责1RemoveAlphabetsHandler.javaString → String剔除所有字母字符2RemoveDigitsHandler.javaString → String剔除所有数字字符3ConvertToCharArrayHandler.javaString → char[]把字符串转换为字符数组阶段一移除字母RemoveAlphabetsHandler 借助IntPredicate与Character::isAlphabetic用流式 API 过滤掉所有字母class RemoveAlphabetsHandler implements HandlerString, String { private static final Logger LOGGER LoggerFactory.getLogger(RemoveAlphabetsHandler.class); Override public String process(String input) { var inputWithoutAlphabets new StringBuilder(); var isAlphabetic (IntPredicate) Character::isAlphabetic; input .chars() .filter(isAlphabetic.negate()) .mapToObj(x - (char) x) .forEachOrdered(inputWithoutAlphabets::append); var inputWithoutAlphabetsStr inputWithoutAlphabets.toString(); LOGGER.info( String.format( Current handler: %s, input is %s of type %s, output is %s, of type %s, RemoveAlphabetsHandler.class, input, String.class, inputWithoutAlphabetsStr, String.class)); return inputWithoutAlphabetsStr; } }实现要点input.chars()把字符串转成IntStreamfilter(isAlphabetic.negate())保留非字母字符再转回char逐个拼接同时每个阶段都通过 SLF4J 记录自己的输入输出及类型为后续运行日志演示做准备。阶段二移除数字RemoveDigitsHandler 与阶段一逻辑同构只是把谓词换成Character::isDigit剔除输入中的所有数字字符。它同样返回String因此可以无缝衔接在阶段一之后。阶段三类型转换ConvertToCharArrayHandler 展示了一个关键能力——阶段之间可以变换数据类型class ConvertToCharArrayHandler implements HandlerString, char[] { private static final Logger LOGGER LoggerFactory.getLogger(ConvertToCharArrayHandler.class); Override public char[] process(String input) { var characters input.toCharArray(); var string Arrays.toString(characters); LOGGER.info( String.format( Current handler: %s, input is %s of type %s, output is %s, of type %s, ConvertToCharArrayHandler.class, input, String.class, string, Character[].class)); return characters; } }该阶段的输出类型从String变为char[]恰好验证了 Pipeline 泛型设计的灵活性只要满足下一阶段的输入类型要求任意阶段都可以自由切换数据类型。组装并执行管道在 App.java 的main方法中管道被流畅地组装并执行public static void main(String[] args) { LOGGER.info(Creating pipeline); var filters new Pipeline(new RemoveAlphabetsHandler()) .addHandler(new RemoveDigitsHandler()) .addHandler(new ConvertToCharArrayHandler()); var input GoYankees123!; LOGGER.info(Executing pipeline with input: {}, input); var output filters.execute(input); LOGGER.info(Pipeline output: {}, output); }对应的真实运行日志来自 英文 README直观展示了数据在三个阶段间的流转07:34:27.069 [main] INFO com.iluwatar.pipeline.App -- Creating pipeline 07:34:27.072 [main] INFO com.iluwatar.pipeline.App -- Executing pipeline with input: GoYankees123! 07:34:27.074 [main] INFO com.iluwatar.pipeline.RemoveAlphabetsHandler -- Current handler: class com.iluwatar.pipeline.RemoveAlphabetsHandler, input is GoYankees123! of type class java.lang.String, output is 123!, of type class java.lang.String 07:34:27.075 [main] INFO com.iluwatar.pipeline.RemoveDigitsHandler -- Current handler: class com.iluwatar.pipeline.RemoveDigitsHandler, input is 123! of type class java.lang.String, output is !, of type class java.lang.String 07:34:27.075 [main] INFO com.iluwatar.pipeline.ConvertToCharArrayHandler -- Current handler: class com.iluwatar.pipeline.ConvertToCharArrayHandler, input is ! of type class java.lang.String, output is [!], of type class [Ljava.lang.Character; 07:34:27.075 [main] INFO com.iluwatar.pipeline.App -- Pipeline output: [!]可以清晰看到数据流GoYankees123!→去除字母→123!→去除数字→!→转字符数组→[!]输出顺序与输入顺序完全一致。测试验证仓库提供了专门的单元测试 PipelineTest.java用一组更复杂的输入验证整条管道的行为Test void testAddHandlersToPipeline() { var filters new Pipeline(new RemoveAlphabetsHandler()) .addHandler(new RemoveDigitsHandler()) .addHandler(new ConvertToCharArrayHandler()); assertArrayEquals( new char[] {#, !, (, , %, #, !}, filters.execute(#H!E(LL0O%THE3R#34E!)); }输入#H!E(LL0O%THE3R#34E!经过去除字母与数字后只剩下特殊字符#!(%#!被转换为对应的char[]并断言相等。该测试同时验证了管道可以接受任意长度的输入、各阶段可以顺序复用、最终结果类型与断言一致。另外 AppTest.java 负责验证main方法的可执行性。模式图示下面这张类图展示了 Pipeline 模式在示例中的静态结构Handler 接口、三个具体 Handler 与 Pipeline 的关系以及数据从String到char[]的类型流向适用场景Aplicabilidad根据文档localization/es/pipeline/README.md在以下情况应当使用管道模式需要按顺序执行多个独立阶段来产出最终值——每个阶段专注做一件事希望为复杂的操作序列增加可读性——管道通过流畅的构建器fluent builder风格接口new Pipeline(...).addHandler(...).addHandler(...)把繁琐的嵌套调用变得平铺直叙希望提升代码的可测试性——由于每个阶段大概率只做单一职责天然符合单一职责原则SRP可以单独为每个阶段编写测试也可以整体测试管道如 PipelineTest.java 所示。典型应用领域在真实世界中管道模式的影子无处不在见 英文 README数据转换与 ETL 流程抽取Extract→ 转换Transform→ 加载Load每一环都是一级管道编译器词法分析、语法分析、语义分析、代码生成正是经典的多阶段流水线图像处理多个滤镜按顺序叠加处理图像日志框架消息依次经过格式化、过滤、输出等多个 handler。已知使用实例文档列举了三类广为人知的管道形态java.util.StreamJava 8 起的流式 API 天然支持filter → map → collect式的管道化处理Maven 构建生命周期validate → compile → test → package等阶段正是构建管道Functional Java函数式编程库中典型的组合式处理。优点与代价Benefits and Trade-offs优点解耦Decoupling每个阶段是独立组件系统更模块化、更易维护阶段之间互不了解只依赖统一的 Handler 契约可复用Reusability单个阶段可以被不同管道重复使用可扩展Extensibility新增阶段无需修改已有阶段只需在链上追加可扩展性/并行潜力Scalability不同阶段可以运行在不同处理器或线程上实现流水线并行。代价复杂度Complexity数据在多阶段间流转整体控制流被分散增大了理解成本性能开销Performance Overhead每个阶段都引入上下文切换与数据传递的开销调试困难Debugging Difficulty数据流经多个组件定位问题比单块代码更费力。相关模式辨析Chain of Responsibility责任链两者都让数据流经一串 handler但责任链中的 handler可以选择不再向下传递链可能提前终止而管道中数据必须依次流过所有阶段Decorator装饰器两者都涉及动态添加行为但装饰器是在对象周围包裹附加行为管道则是按离散步骤处理数据Composite组合两者都涉及层级处理但组合更关注部分—整体的树形结构管道更关注线性顺序流。动手实践在仓库中运行示例本模块是 java-design-patterns 仓库的独立 Maven 子项目pom.xml可以在仓库根目录下执行以下命令运行示例与测试# 运行管道示例App 的 main 方法输出上述日志 ./mvnw -pl pipeline exec:java -Dexec.mainClasscom.iluwatar.pipeline.App # 运行模块单元测试 ./mvnw -pl pipeline test提示./mvnw是仓库自带的 Maven Wrapper无需本地预装 Maven。若需在 IDE 中运行直接以com.iluwatar.pipeline.App为主类、以pipeline模块的 test 源码集运行 PipelineTest 即可。总结管道模式用极简的代码一个接口、一个组合类换来了极强的模块化表达能力类型安全由泛型在编译期保障阶段解耦由 Handler 契约实现流程可读性由流畅的链式构建器提升可测试性由单一职责的细粒度阶段保证。无论你是在构建 ETL 任务、编译器前端还是想为复杂的字符串/数据变换找到优雅的抽象java-design-patterns 中这个 30 余行的 Pipeline.java 都是可以直接借鉴的范本。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐原型模式Prototype PatternJava 实战指南基于 java-design-patterns 的克隆创建深入解析原型模式Prototype PatternJava 实战指南基于 java design patterns 的克隆创建深入解析 原型模式Prototyp示例工程教程Java 回调模式Callback Pattern详解基于 java-design-patterns 的异步通信实现指南Java 回调模式Callback Pattern详解基于 java design patterns 的异步通信实现指南 本文以 java design示例工程教程Java 领域模型模式Domain Model Pattern实战指南以 java-design-patterns 仓库为例Java 领域模型模式Domain Model Pattern实战指南以 java design patterns 仓库为例 领域模型模式Domain示例工程教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考