管道-过滤器结构模式
简介代码实现1、定义一个管道接口2、定义一个管道上下文流转抽象3、定义一个抽象阀门4、实现管道接口5、定义阀门按照业务逻辑组装管道-阀门简介
在管道和过滤器软件体系结构中,每个模块都有一个输入和一个输出。它采用流水线的方式对数据进行作业。类似我们生活中的管道,过滤器相当于管道上的阀门。我们在每个阀门上进行一定的数据计算,并将得到的结果传递给下个阀门。这种有序的数据处理就是我们所说的管道-过滤器模式。
它的优点在于可以将整个计算提示分解为多个计算行为的叠加组合,通过管道过滤器结构我们可以将复杂的计算分解,达到化烦为简的目的。同时任意两个过滤只要他们遵守同样的要约,那么他们就可以进行组合,这一点可以提高代码的复用。同时过滤器的顺序可以自由调节,程序设计灵活多变。学习管道过滤器模式我们需要了解两个属于
Pipeline:管道,相当于车间的生产线,是一套明确的逻辑处理总线。
Valve: 阀门,相当于生产线上的工人,负责完成各自职责内的工作。
那么我们如何实现管道过滤器模式呢?
代码实现
1、定义一个管道接口
/*** @author FeianLing* @date /7/12*/public interface Pipeline {/*** @author FeianLing* @date /7/12* @desc 设计基础阀门,一个管道必须基本有一个基本阀门* @param [bases]* @return void*/boolean setBases(AbstractValve valve);/*** @author FeianLing* @date /7/12* @desc 添加阀门信息* @param [valve]* @return void*/boolean addValve(AbstractValve valve);/*** @author FeianLing* @date /7/12* @desc 移除管道中的阀门* @param [valve]* @return void*/boolean removeValve(AbstractValve valve);/*** @author FeianLing* @date /7/12* @desc 调用管道处理数据* @param []* @return void*/void invoke();}
2、定义一个管道上下文流转抽象
public interface PipelineContext {/*** @author FeianLing* @date /7/12* @desc 调用下一个阀门* @param []* @return void*/void invokeNext();}
3、定义一个抽象阀门
public abstract class AbstractValve {/*** @author FeianLing* @date /7/12* @desc 当前阀门需要的处理逻辑* @param [context] d.* @return void*/abstract void execute(PipelineContext context);/*** @author FeianLing* @date /7/12* @desc 调用阀门* @param [context]* @return void*/void invoke(PipelineContext context) {execute(context);context.invokeNext();}}
4、实现管道接口
public class StandardPipeline implements Pipeline {/** 阀门集合 */private List<AbstractValve> valves;/** 基础阀门 */private AbstractValve bases;/** 管道流转的上下文,可根据业务需要在上下文中加入流转的数据 */private PipelineContext context;public StandardPipeline() {valves = new ArrayList<>();context = new StandardPipelineContext();}@Overridepublic boolean setBases(AbstractValve valve) {bases = valve;return true;}@Overridepublic boolean addValve(AbstractValve valve) {return valves.add(valve);}@Overridepublic boolean removeValve(AbstractValve valve) {if (valves.contains(valve)) {return valves.remove(valve);}return true;}@Overridepublic void invoke() {context.invokeNext();}/** 定义一个管道上下文内部类 实现管道上下文接口 */private class StandardPipelineContext implements PipelineContext {int index = 0;@Overridepublic void invokeNext() {if (!valves.isEmpty() && index < valves.size()) {valves.get(index++).invoke(context);} else {bases.execute(context);}}}}
5、定义阀门
//首先定义一个基础的阀门@Slf4jpublic class BaseValve extends AbstractValve {@Overridevoid execute(PipelineContext context) {log.info("BaseValve > invoke > {}", context);}}//下面我们在定义几个阀门来测试@Slf4jpublic class Valve1 extends AbstractValve {@Overridevoid execute(PipelineContext context) {log.info("Valve1 > invoke >{}", context);}}@Slf4jpublic class Valve2 extends AbstractValve {@Overridevoid execute(PipelineContext context) {log.info("Valve2 > invoke > {}", context);}}@Slf4jpublic class Valve3 extends AbstractValve {@Overridevoid execute(PipelineContext context) {log.info("Valve3 > invoke > {}", context);}}
按照业务逻辑组装管道-阀门
管道组装代码如下所示,我们预期的数据处理流转是 阀门1 -> 阀门3 ->阀门2 -> 基础阀门。
public class PipelineTest {public static void main(String[] args) {StandardPipeline pipeline = new StandardPipeline();BaseValve baseValve = new BaseValve();Valve1 valve1 = new Valve1();Valve2 valve2 = new Valve2();Valve3 valve3 = new Valve3();pipeline.setBases(baseValve);pipeline.addValve(valve1);pipeline.addValve(valve3);pipeline.addValve(valve2);pipeline.invoke();}}
通过执行main方法,打印结果如下。
如果你觉得本文还不错,还请不吝打赏。