Java Behavioral 行为型模式之 Pipeline Pattern 管道模式

250 阅读3分钟

Java Behavioral 行为型模式之 Pipeline Pattern 管道模式

  • 管道模式是责任链模式的常用变种之一,如果下一个步骤不依赖上一个步骤输出结果的话,那么可以改用责任链模式
  • 管道模式可以看做是一个流水线作业,固定顺序步骤依次线性执行,每个步骤环节(阶段)都依赖上个环节的输出
  • 每个步骤不管处不处理都会传递到下一个步骤,数据或任务在一个阶段被处理(加工)完成后,随即继续进入下一个阶段去处理
  • 管道模式将多个处理步骤有序的连接在一起,使得数据处理流程更加清晰和模块化,每个步骤都可以进行独立测试和维护,从而提高了代码的可读性、可拓展性和可维护性

常规写法

Pipe 接口

interface Pipe<I, O> {
    O process(I input);
}

若干个 Pipe 接口的现实类

class TrimProcessor implements Pipe<String, String> {
    @Override
    public String process(String input) {
        return input.trim();
    }
}

class UpperCaseProcessor implements Pipe<String, String> {
    @Override
    public String process(String input) {
        return input.toUpperCase();
    }
}

使用

 public static void main(String[] args) {
    String input = " Hello World  ";
    Pipe<String, String> firstPipe = new TrimProcessor();
    Pipe<String, String> secondPipe = new UpperCaseProcessor();
    String output = secondPipe.process(firstPipe.process(input));
    System.out.println("Input: '" + input + "'");
    System.out.println("Output: '" + output + "'");
    }
    //结果
    //Input: ' Hello World  '
    //Output: 'HELLO WORLD'

采用函数式接口

Pipe 接口用 java.util.function.Function (是一个函数式接口)替代

若干个 Pipe 接口的现实类

class TrimProcessor implements Function<String, String> {
    @Override
    public String apply(String input) {
        return input.trim();
    }
}
class UpperCaseProcessor implements Function<String, String> {
    @Override
    public String apply(String input) {
        return input.toUpperCase();
    }
}
 String input = " Hello World  ";
 Function<String, String> firstPipe = new TrimProcessor();
 Function<String, String> secondPipe = new UpperCaseProcessor();
 String output = secondPipe.apply(firstPipe.apply(input));
 System.out.println("Input: '" + input + "'");
 System.out.println("Output: '" + output + "'");

引入 Lambda 表达式

现实类也可以用 Lambda 表达式简化

 String input = " Hello World  ";
 Function<String, String> firstPipe = it -> it.trim();
 Function<String, String> secondPipe = it -> it.toUpperCase();
 String output = secondPipe.apply(firstPipe.apply(input));
 System.out.println("Input: '" + input + "'");
 System.out.println("Output: '" + output + "'");

方法引用继续简化

 String input = " Hello World  ";
 Function<String, String> firstPipe = String::trim;//方法引用
 Function<String, String> secondPipe = String::toUpperCase;//方法引用
 String output = secondPipe.apply(firstPipe.apply(input));
 System.out.println("Input: '" + input + "'");
 System.out.println("Output: '" + output + "'"); 

可以用 andThen 和 compose 连写

 String input = " Hello World  ";
 Function<String, String> firstPipe = String::trim;//方法引用
 Function<String, String> secondPipe = String::toUpperCase;//方法引用
 Function<String, Integer> thirdPipe = String::length;//方法引用
 //...
 Function<String, Integer> pipeline = firstPipe.andThen(secondPipe).andThen(thirdPipe);
//        Function<String, String> pipeline = firstPipe.compose(secondPipe);
 Integer outputLen = pipeline.apply(input);
 System.out.println("InputLen: '" + input.length() + "'");
 System.out.println("OutputLen: '" + outputLen + "'");

应用场景

  • 1 日志处理和记录(过滤、解析、存储等)
  • 2 审批处理和验证(验证、审批等)
  • 3 数据清理和处理(清洗、转换、分析等)
  • 4 图像视频处理(缩放、旋转、滤镜、压缩等)
        //1准备数据
        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        //2定义数据处理步骤
        
        // 偶数
        Function<List<Integer>, List<Integer>> filterEven = list -> list.stream()
                .filter(n -> n % 2 == 0)
                .collect(Collectors.toList());
        // 除法
        Function<List<Integer>, List<Integer>> divisionByTwo = list -> list.stream()
                .map(n -> n / 2)
                .collect(Collectors.toList());
        // 求和
        Function<List<Integer>, Integer> sum = list -> list.stream()
                .mapToInt(Integer::intValue)
                .sum();

        //3构建管道
        Function<List<Integer>, Integer> pipeline = filterEven
                .andThen(filterEven)
                .andThen(divisionByTwo)
                .andThen(sum);

        //4执行管道
        int result = pipeline.apply(numbers);
        System.out.println("Result: " + result); //  Result: 15

管道模式特点

  • 1 模块化:复杂业务拆分成每个处理步骤都是一个独立的模块,逻辑清晰了,也可以单独开发和测试
  • 2 顺序执行:处理步骤按照定义的顺序依次执行,像流水线一样
  • 3 可扩展性:可以轻松地添加新的处理步骤或修改现有的步骤,而不影响整个系统的结构
  • 4 可重用性:处理步骤可以在不同的管道中重复使用