知识卡片

管道-过滤器风格

结构图卡

内容

管道-过滤器风格最早出现在UNIX中,适用于对有序数据进行一系列已定义独立计算的应用程序。每个组件(过滤器)都有一组输入集和输出集,从输入源读入数据流、在输出池产生输出数据流,并对输入流做内部转换和增量计算——因此在输入数据流被全部处理之前,输出就已经开始了,这是它区别于批处理序列的关键:过滤器必须是独立实体,不能与其他过滤器共享状态,也无须知道连接到自己的其他过滤器的存在,只关注自己输入输出管道上的数据流;整体输出结果的正确性不应依赖内部过滤器的执行顺序。若某个过滤器把输入当作一个单一实体整体处理完才产生输出,管道就不再提供”数据流”的增量效果,整个系统退化为批处理序列——这种退化是该风格最容易被误用的地方。优点包括:组件行为互不影响,系统易理解;只要数据格式一致任意两个过滤器都能连接,支持重用;新过滤器易加入、旧过滤器可被替换,易维护扩展;支持吞吐量分析、死锁分析等专属分析;支持并发执行。缺点包括:容易被误用退化为批处理风格;不适用于交互性很强的应用(增量显示与过滤器输出数据的粒度差距太大);数据传输时可能被迫采用底层公共命名格式,增加解析/反解析的额外复杂度。传统编译器常被当作该风格的典型案例,但实际上编译器各阶段(词法/语法/语义分析)共享一张独立于数据流之外的符号表,用纯管道-过滤器描述并不精确,现代编译器结构更多表示为以数据为中心的黑板系统架构风格。

结构图

flowchart LR
    A[数据源] --> F1[过滤器1<br/>独立实体,不共享状态]
    F1 -->|管道:信息流导管| F2[过滤器2]
    F2 -->|管道| F3[过滤器3]
    F3 --> B[数据汇]
    S[(共享符号表<br/>独立于数据流之外)] -.被各过滤器读写.-> F1
    S -.-> F2
    S -.-> F3

参考来源

- 位置:《软件架构理论与实践》第4章《软件架构的风格与模式》"4.3.1 管道-过滤器风格"节(源文件:_epub-src/OEBPS/text00034.html) - 结论依据:原文说明过滤器"不能与其他过滤器共享状态,并且该过滤器无须知道与其输入管道和输出管道所连接的其他过滤器的存在",并说明"大多数编译器在进行词法分析时会生成一个独立的词汇表……该表不随着数据流经过各个阶段,而是独立于所有的过程之外",直接支撑本卡片的结构图与内容解释。 - 原始内容:组件从输入源读入数据流,并在输出池产生输出数据流,组件对输入流进行内部转换和增量计算,因此在输入数据流被全部处理之前,输出就已经开始了……虽然它最初更接近批处理架构风格,即每一部分完成工作后下一部分才会开始。