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

软件架构风格系列(3):管道 - 过滤器架构


文章目录

  • 前言
  • 一、从生活场景到架构原理,看懂管道 - 过滤器的核心逻辑
    • (一)什么是管道 - 过滤器架构?
    • (二)核心组件拆解
  • 二、架构设计图:一图看懂管道 - 过滤器架构全貌
  • 三、Java 示例代码:手把手教你实现管道 - 过滤器架构
    • (一)定义过滤器接口
    • (二)实现具体过滤器
    • (三)实现管道类
    • (四)使用示例
  • 四、管道 - 过滤器架构的优势与适用场景
    • (一)核心优势
    • (二)适用场景
  • 五、使用管道 - 过滤器架构的注意事项
  • 总结

前言

在互联网技术的高速发展中,系统架构的设计直接影响着软件的性能与可维护性。当你在使用 ETL 工具处理海量数据,或是在编译器中实现代码的层层解析时,背后往往都有一个低调却强大的架构风格在支撑 —— 管道 - 过滤器架构。作为一个在系统架构领域摸爬滚打多年的老湿机,今天就来和大家深度剖析这个 “数据处理利器”,带你从理论到实践吃透它!

一、从生活场景到架构原理,看懂管道 - 过滤器的核心逻辑

(一)什么是管道 - 过滤器架构?

**管道 - 过滤器架构,顾名思义,其灵感来源于现实生活中的流水线作业。**想象一下工厂里的汽车组装流水线,每个工位的工人负责特定的组装步骤,零件依次从一个工位传递到下一个工位,最终完成汽车的组装。

在软件架构中,“过滤器” 就如同流水线上的工位工人,负责对数据进行特定处理;“管道” 则是连接这些工位的传送带,负责将数据从一个过滤器传输到下一个过滤器。

每个过滤器都有明确的输入和输出,它们相互独立,只专注于自己的处理任务,如数据清洗、格式转换、逻辑校验等。数据通过管道在各个过滤器之间流动,形成一条完整的数据处理链路。

例如,在一个日志分析系统中,数据首先经过 “日志采集过滤器” 收集原始日志,然后通过管道传递给 “日志清洗过滤器” 去除无效信息,接着再传递给 “日志分析过滤器” 提取关键数据,最后输出分析结果。

(二)核心组件拆解

过滤器(Filter):过滤器是无状态的处理单元,它只根据输入数据产生输出,不会受到其他过滤器或系统状态的影响。比如在编译器中,“词法分析过滤器” 会将源代码分解成一个个单词,不依赖后续的语法分析过程。

管道(Pipe):管道负责数据的传输,它可以是同步传输,也可以是异步传输,甚至支持数据缓冲。像 Unix 系统中的管道符 “|”,就是典型的管道实现,它能将一个命令的输出作为另一个命令的输入。在软件系统中,消息队列(如 Kafka)也可以充当管道的角色,实现数据在不同过滤器之间的异步传递。

数据流(Data Flow):数据流决定了数据在过滤器之间的流动方向和顺序。它支持增量处理,即前一个过滤器无需完全处理完所有数据,就可以将部分结果传递给下一个过滤器,从而提高整体处理效率。

二、架构设计图:一图看懂管道 - 过滤器架构全貌

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这张架构设计图中,最上方的 A 节点代表数据源,数据从这里开始进入处理流程。紧接着是一系列的过滤器(B - F),每个过滤器负责不同的数据处理任务。数据通过管道(管道 1 - 管道 3)在过滤器之间有序流动,最终到达数据目标 G,完成整个数据处理过程。通过这张图,我们可以清晰地看到管道 - 过滤器架构中各组件之间的关系和数据的流向。

三、Java 示例代码:手把手教你实现管道 - 过滤器架构

(一)定义过滤器接口

public interface Filter<T> {//对输入数据进行处理并返回处理结果T process(T input);
}

这里定义了一个泛型接口Filter,它只有一个方法process,用于对输入数据进行处理并返回处理结果。

(二)实现具体过滤器

以一个简单的文本处理为例,我们实现两个过滤器:“文本大写转换过滤器” 和 “文本添加前缀过滤器”。

// 文本大写转换过滤器
public class UppercaseFilter implements Filter<String> {@Overridepublic String process(String input) {return input.toUpperCase();}
}// 文本添加前缀过滤器
public class PrefixFilter implements Filter<String> {@Overridepublic String process(String input) {return "处理后: " + input;}
}

(三)实现管道类

import java.util.ArrayList;
import java.util.List;public class Pipeline<T> {private final List<Filter<T>> filters = new ArrayList<>();//向管道中添加过滤器public Pipeline<T> addFilter(Filter<T> filter) {this.filters.add(filter);return this;}//按照顺序依次调用每个过滤器的process方法,对输入数据进行处理public T execute(T input) {T output = input;for (Filter<T> filter : filters) {output = filter.process(output);}return output;}
}

Pipeline类中,我们使用一个List来存储过滤器。addFilter方法用于向管道中添加过滤器,execute方法则按照顺序依次调用每个过滤器的process方法,对输入数据进行处理。

(四)使用示例

public class Main {public static void main(String[] args) {Pipeline<String> pipeline = new Pipeline<>();pipeline.addFilter(new UppercaseFilter()).addFilter(new PrefixFilter());String input = "hello world";String result = pipeline.execute(input);System.out.println(result);}
}

main方法中,我们创建了一个Pipeline对象,并向其中添加了两个过滤器。然后输入一段文本 “hello world”,经过管道处理后,最终输出 “处理后: HELLO WORLD”。

四、管道 - 过滤器架构的优势与适用场景

(一)核心优势

高内聚低耦合:每个过滤器独立完成自己的任务,与其他过滤器之间的耦合度极低。例如在电商系统的订单处理中,“库存检查过滤器” 和 “支付处理过滤器” 可以独立开发和维护,一个过滤器的修改不会影响到另一个。

可扩展性强:当业务需求发生变化,需要增加新的数据处理逻辑时,只需新增一个过滤器并将其添加到管道中即可,无需对整个系统进行大规模改动。

支持并行处理:多个过滤器可以并行运行,提高数据处理效率。比如在图像处理系统中,“图像缩放过滤器” 和 “图像色彩调整过滤器” 可以同时对图像进行处理。

(二)适用场景

数据处理系统:如 ETL(Extract - Transform - Load)工具,用于从不同数据源提取数据,进行转换后加载到数据仓库中。

编译器:编译器的各个阶段(词法分析、语法分析、语义分析等)可以看作是过滤器,通过管道依次处理源代码。

Web 应用中间件:在 Web 应用中,请求处理过程可以使用管道 - 过滤器架构,例如通过过滤器实现请求日志记录、身份认证、参数校验等功能。

五、使用管道 - 过滤器架构的注意事项

虽然管道 - 过滤器架构有诸多优势,但也并非适用于所有场景。在使用时需要注意:

数据格式一致性:各个过滤器之间的数据格式需要保持一致,否则在管道传输过程中可能会出现问题。这就要求在设计过滤器时,明确输入和输出的数据格式标准。

性能开销:如果管道中过滤器数量过多,数据在管道中的传输和处理可能会带来一定的性能开销。因此需要合理规划过滤器的数量和处理逻辑,避免性能瓶颈。

错误处理:由于过滤器之间相互独立,当某个过滤器出现错误时,需要有完善的错误处理机制,确保不会影响整个系统的稳定性。

总结

管道 - 过滤器架构它就像一把 “瑞士军刀”,在数据处理领域有着广泛的应用和强大的能力。无论是在实际项目中,还是在技术学习过程中,掌握这种架构风格都能为我们带来更多的思路和解决方案。


图片来源网络

相关文章:

  • JavaScript - JavaScript 运算符之圆括号运算符与方括号运算符(圆括号运算符概述、圆括号运算符用法、方括号运算符概述、方括号运算符用法)
  • 方案精读:122页智能制造APS MES信息化系统技术方案【附全文阅读】
  • opencloudos 安装 mosquitto
  • UNiAPP地区选择
  • MySQL的缓存策略
  • Femap许可优化策略
  • 学习日志09 java
  • 中级统计师-统计学基础知识-第一章
  • spring框架的JDBC模板技术
  • lesson03-简单回归案例(理论+代码)
  • GTS-400 系列运动控制器板卡介绍(三十四)---运动程序多线程累加求和
  • 练习小项目3:随机正能量语录生成器
  • C语言—指针4
  • EXCEL在一列数据前统一添加负号
  • 【Manim】使用manim画一个高斯分布的动画
  • 黑马k8s(八)
  • Spring MVC 对 JavaWeb 的优化:从核心组件到注解
  • 使用 LSTM/GRU 预测设备异常的模型
  • 前端 vue 部署 nginx 请求 404
  • MCP概述及MCP Server的使用和实现(谷歌ADK使用MCP Server)
  • 全国林业院校校长论坛举行,聚焦林业教育的创新与突破
  • 白玉兰奖征片综述丨海外剧创作趋势观察:跨界·融变·共生
  • 专家:家长要以身作则,孩子是模仿者学习者有时也是评判者
  • “大型翻车现场”科技满满,黄骅打造现代化港口和沿海新城典范
  • 马上评|这种“维权”已经不算薅羊毛,涉嫌犯罪了
  • 与总书记交流的上海人工智能实验室年轻人,在探索什么前沿领域?