本文转载自微信公众号「JavaKeeper」,让们作者海星。起学转载本文请联系JavaKeeper公众号。习管 管道模式,道模不属于23种设计模式之一(是让们责任链模式的一种变体),但是起学在我们实际业务架构中还是有很多场景适用的,主要用于将复杂的习管进程分解成多个独立的子任务,像流水线一样去执行,道模了解一下呗 假设我们有这样的起学一个需求,读取文件内容,习管并过滤包含 “hello” 的道模字符串,然后将其反转 Linux 一行搞定 用世界上最好语言 Java 实现也很简单 再假设我们上边的场景是在一个大型系统中,有这样的起学数据流需要多次进行复杂的逻辑处理,还是习管简单粗暴的把一系列流程像上边那样放在一个大组件中吗? 这样的设计完全违背了单一职责原则,我们在增改,或者减少一些处理逻辑的时候,亿华云就必须对整个组件进行改动。可扩展性和可重用性几乎没有~~ 那有没有一种模式可以将整个处理流程进行详细划分,划分出的每个小模块互相独立且各自负责一小段逻辑处理,这些小模块可以按顺序连起来,前一模块的输出作为后一模块的输入,最后一个模块的输出为最终的处理结果呢? 如此一来修改逻辑时只针对某个模块修改,添加或减少处理逻辑也可细化到某个模块颗粒度,并且每个模块可重复利用,可重用性大大增强。 恩,这就是我们要说的管道模式 管道模式(Pipeline Pattern) 是责任链模式(Chain of Responsibility Pattern)的常用变体之一。 顾名思义,管道模式就像一条管道把多个对象连接起来,整体看起来就像若干个阀门嵌套在管道中,而处理逻辑就放在阀门上,需要处理的对象进入管道后,分别经过各个阀门,每个阀门都会对进入的对象进行一些逻辑处理,经过一层层的处理后从管道尾出来,此时的高防服务器对象就是已完成处理的目标对象。 管道模式用于将复杂的进程分解成多个独立的子任务。每个独立的任务都是可复用的,因此这些任务可以被组合成复杂的进程。 PS:纯的责任链模式在链上只会有一个处理器用于处理数据,而管道模式上多个处理器都会处理数据。 管道模式:对于管道模式来说,有 3 个对象: 程序员还是看代码消化才快些,我们用管道模式实现下文章开头的小需求 1、处理器(管道的各个阶段) 2、定义具体的处理器(阀门) 产品他么的源码库又来了,这次是删除 hello.txt 中的 world 字符 三下五除二,精通 shell 编程的我搞定了 Java 怎么搞,你应该很清晰了吧 Pipeline 模式的核心思想是将一个任务处理分解为若干个处理阶段(Stage),其中每个处理阶段的输出作为下一个处理阶段的输入,并且各个处理阶段都有相应的工作者线程去执行相应的计算。因此,处理一批任务时,各个任务的各个处理阶段是并行(Parallel)的。通过并行计算,Pipeline 模式使应用程序能够充分利用多核 CPU 资源,提高其计算效率。 ——《Java 多线程编程实战指南》 优点 模式需要注意的东西 如果,你的管道逻辑真的很简单,也直接用 Java8 提供的 Function 就,具体实现如下这样 但是,并不是一碰到这种类似流式处理的任务就需要用管道,Pipeline 模式中各个处理阶段所用的工作者线程或者线程池,表示各个阶段的输入/输出对象的创建和一定(进出队列)都有其自身的时间和空间开销,所以使用 Pipeline 模式的时候需要考虑它所付出的代价。建议处理规模较大的任务,否则可能得不偿失。 参考 https://java-design-patterns.com/patterns/pipeline/ https://developer.aliyun.com/article/778865 https://yasinshaw.com/articles/108 《Java多线程编程实战指南(设计模式篇)》一、让们开场
二、定义
三、角色
四、实例
3、管道
public class Pipeline<I,O> { private final Handler<I,O> currentHandler; Pipeline(Handler<I, O> currentHandler) { this.currentHandler = currentHandler; } <K> Pipeline<I, K> addHandler(Handler<O, K> newHandler) { return new Pipeline<>(input -> newHandler.process(currentHandler.process(input))); } O execute(I input) { return currentHandler.process(input); } } 4、 客户端使用
import lombok.val; public class ClientTest { public static void main(String[] args) { File file = new File("/Users/apple/Documents/hello.txt"); val filters = new Pipeline<>(new FileProcessHandler()) .addHandler(new CharacterFilterHandler()) .addHandler(new CharacterReverseHandler()); System.out.println(filters.execute(file)); } } 5、结果
UML 类图
五、优缺点
六、Java Function
最后