Java 管道设计模式实现

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39947155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:35:07  来源:igfitidea点击:

Pipeline design pattern implementation

javaoopdesign-patternsdesign-principles

提问by Prashant Chauhan

This is a design question regarding the implementation of a Pipeline. The following is my naive implementation.

这是一个关于流水线实现的设计问题。以下是我的幼稚实现。

Interface for individual steps/stages in the pipeline:

管道中各个步骤/阶段的接口:

public interface Step<T, U> {
    public U execute(T input);
}

Concrete implementations of steps/stages in pipeline:

流水线中步骤/阶段的具体实现:

public class StepOne implements Step<Integer, Integer> {
    @Override
    public Integer execute(Integer input) {
        return input + 100;
    }
}

public class StepTwo implements Step<Integer, Integer> {
    @Override
    public Integer execute(Integer input) {
        return input + 500;
    }
}

public class StepThree implements Step<Integer, String> {
    @Override
    public String execute(Integer input) {
        return "The final amount is " + input;
    }
}

The pipeline class will hold/register the steps in the pipeline and execute them one after the other:

管道类将保存/注册管道中的步骤并一个接一个地执行它们:

public class Pipeline {
    private List<Step> pipelineSteps = new ArrayList<>();
    private Object firstStepInput = 100;

    public void addStep(Step step) {
        pipelineSteps.add(step);
    }

    public void execute() {
        for (Step step : pipelineSteps) {
            Object out = step.execute(firstStepInput);
            firstStepInput = out;
        }
   }
}

Diver program to execute the pipeline:

执行管道的 Diver 程序:

public class Main {
    public static void main(String[] args) {
        Pipeline pipeline = new Pipeline();
        pipeline.addStep(new StepOne());
        pipeline.addStep(new StepTwo());
        pipeline.addStep(new StepThree());

        pipeline.execute();
    } 
}

However, as you can see the naive implementation has many limitations.

但是,正如您所看到的,简单的实现有很多限制。

One of the major ones is that since the requirement is that the output of each step could be of any type, the naive implementation is not type-safe (the execute method in the Pipeline class). If I happen to wire the steps in the pipeline incorrectly, the app will fail.

主要问题之一是,由于要求每个步骤的输出可以是任何类型,因此幼稚的实现不是类型安全的(Pipeline 类中的 execute 方法)。如果我碰巧错误地连接了管道中的步骤,应用程序将失败。

Can anyone help me design the solution by adding to what I have coded, or point me towards an already existing pattern to solve this?

任何人都可以通过添加到我已经编码的内容来帮助我设计解决方案,或者指出我已经存在的模式来解决这个问题?

采纳答案by Grim

I would focus on

我会专注于

If I happen to wire the steps in the pipeline incorrectly, the app will fail.

如果我碰巧错误地连接了管道中的步骤,应用程序将失败。

Yes, this is a problem. StepThreeis the stranger here. I do not think one simple pattern might help, I do think it must be a combination of strategy and builder pattern. For example:

是的,这是一个问题。StepThree是这里的陌生人。我不认为一个简单的模式可能会有帮助,我认为它必须是策略和构建器模式的组合。例如:

Pipeline<Integer,Integer> intPipe = new Pipeline<>();
intPipe = intPipe.add(new StepOne()); // increment 100
intPipe = intPipe.add(new StepTwo()); // increment 500
Pipeline<String, Integer> strPipe = intPipe.add(new StepThree()); // convert

Whereat Pipeline is like this:

其中管道是这样的:

public static class Pipeline<IN, OUT> {
   //...
   public<A> Pipeline<OUT,A> add(Step<IN,A> step) {
     pipelineSteps.add(step);
     return (Pipeline<OUT,A>)this;
   }
}

Using the fast-builder-syntax this might work:

使用 fast-builder-syntax 这可能有效:

Pipeline<String, Integer> pipe = new Pipeline<Integer, Integer>()
    .add(new StepOne()).add(new StepTwo()).add(new StepThree());

This should work since generics are not part of the bytecode.

这应该有效,因为泛型不是字节码的一部分。

回答by Gilbert Le Blanc

Your approach is pretty good. However, I'd code the Pipeline class like this:

你的方法很不错。但是,我会像这样对 Pipeline 类进行编码:

public class Pipeline {
    private List<Step> pipelineSteps = new ArrayList<>();
    private Object firstStepInput = 100;

    public Pipeline() {
        pipelineSteps.add(new StepOne());
        pipelineSteps.add(new StepTwo());
        pipelineSteps.add(new StepThree());
    }

    public void execute() {
        for (Step step : pipelineSteps) {
            Object out = step.execute(firstStepInput);
            firstStepInput = out;
        }
    }

    public String getResult() {
        return (String) firstStepInput;
    }
}

This way, all of the specific step knowledge is encapsulated in the Pipeline class.

这样,所有的具体步骤知识都封装在 Pipeline 类中。

In this case, the execute method can perform a loop. However, the execute class can perform the steps one by one, if necessary.

在这种情况下,execute 方法可以执行一个循环。但是,如果需要,execute 类可以一一执行这些步骤。

回答by holi-java

why do you need an additional Pipelineclass ? I think you can remove the middle man. this will make your api simpler, for example:

为什么需要额外的Pipeline课程?我想你可以去掉中间人。这将使您的 api 更简单,例如:

Step<Integer, String> source = Step.of(Object::toString);
Step<Integer, Integer> toHex = source.pipe(it -> Integer.parseInt(it, 16));

toHex.execute(11/*0x11*/);// return 17;

you can implement your pipeline pattern simply in java-8as below :

您可以简单地在java-8 中实现您的管道模式,如下所示:

interface Step<I, O> {

    O execute(I value);

    default <R> Step<I, R> pipe(Step<O, R> source) {
        return value -> source.execute(execute(value));
    }

    static <I, O> Step<I, O> of(Step<I, O> source) {
        return source;
    }
}

in prior java version you can use an abstract class instead:

在之前的 Java 版本中,您可以改用抽象类:

abstract static class Step<I, O> {

    public abstract O execute(I value);

    public <R> Step<I, R> pipe(Step<O, R> source) {
        return new Step<I, R>() {
            @Override
            public R execute(I value) {
                return source.execute(Step.this.execute(value));
            }
        };
    }

    public static <I, O> Step<I, O> of(Step<I, O> source) {
        return source;
    }
}

回答by Vladimir Stazhilov

You can basically use chain of responsibility design pattern

您基本上可以使用责任链设计模式

回答by murali

public class Pipeline {

    private List<Step> pipelineSteps = new ArrayList<>();
    private Object firstStepInput = 100;

    public Pipeline() {
        pipelineSteps.add(new StepOne());
        pipelineSteps.add(new StepTwo());
        pipelineSteps.add(new StepThree());
}

回答by Júlio Falbo

You don't need to create a new Interface for this.

您不需要为此创建新的接口。

Java 8 already has a Functional Interface called Function and it allows you to create a Chaining of Functions (in other words, your Pipeline).

Java 8 已经有一个名为 Function 的函数式接口,它允许您创建一个函数链(换句话说,您的管道)。

Function<Integer, Integer> addOne = it -> {
            System.out.println(it + 1);
            return it + 1;
        };

Function<Integer, Integer> addTwo = it -> {
            System.out.println(it + 2);
            return it + 2;
        };

Function<Integer, Integer> timesTwo = input -> {
            System.out.println(input * 2);
            return input * 2;
        };

final Function<Integer, Integer> pipe = addOne
        .andThen(timesTwo)
        .andThen(addTwo);

pipe.apply(10);

If you want to read more about Functional Interfaces: https://medium.com/@julio.falbo/java-recent-history-java-8-part-2-functional-interface-predefined-functional-interface-2494f25610d5

如果您想阅读有关功能接口的更多信息:https: //medium.com/@julio.falbo/java-recent-history-java-8-part-2-functional-interface-predefined-functional-interface-2494f25610d5