【问题标题】:Is there an object able to chain successive method calls是否有一个对象能够链接连续的方法调用
【发布时间】:2020-08-07 07:00:05
【问题描述】:

我有几种方法具有以下模式:

int status = method0();
if(status = success){
  status = method1();
}
if(status = success){
  status = method2();
}
if(status = success){
  status = method3();
}
if(status = success){
  status = method4();
}
return status

我想让它更具可读性。我想像这样:

final CommandPipe pipe = new CommandPipe();
status = pipe.next(() -> method0(arg0))
              .next(() -> method1(arg1))
              .next(() -> method2(arg2))
              .next(() -> method3(arg3))
              .next(() -> method4(arg4))
              .getResult();
return status; 

在 Java 8 中是否有对象这样做?

【问题讨论】:

  • 你可以用List<IntSupplier>(或类似的)和一个循环来做到这一点。
  • 我假设您的意思是 if(status == success) 而不是 if(status = success) - 比较而不是赋值,对吧?

标签: java java-8 declarative


【解决方案1】:

目前没有。 由于它的业务案例框架不会提供这样的东西。 您必须自己构造,否则您可以使用 CompletableFuture.supplyAsync 和 thenApply 方法连续更好地利用资源的线程。

【讨论】:

  • 我接受了这个回复,因为它准确地回答了我的问题:它是基于 CompletableFuture 的回复的“否”。谢谢。
【解决方案2】:

我认为最简单的方法是自己实现这样的类型,例如:

public class CommandPipe<T> {
    private Predicate<T> predicate;
    private T lastResult = null;
    private boolean firstInvotion = true;
    public CommandPipe(Predicate<T> predicate) {
      this.predicate = predicate;
    }

    public CommandPipe next(Supplier<T> supplier) {
        boolean doStep;

        if (firstInvotion) {
            firstInvotion = false;
            doStep = true;
        } else {
            doStep = predicate.test(lastResult);
        }

        if (doStep) {
            lastResult = supplier.get();
        } else {
            // error handling
        }

        return this;
    }

    public T getResult() {
        return lastResult;
    }
}

【讨论】:

  • 感谢您的回复,我确实认为实现起来很简单,但找不到提供如此简单实现的对象,感到很惊讶。我在这里问它是为了避免重新发明轮子?
【解决方案3】:

使用 List&lt;IntSupplier&gt; 和 for 循环:

int method(List<IntSupplier> list) {
  int status = success;
  for (Iterator<IntSupplier> it = list.iterator(); status == success && it.hasNext();) {
    status = it.next().get();
  }
  return status;
}

像这样调用:

int status = method(List.of(
    () -> method0(arg0),
    () -> method1(arg1) /* etc */));

(当然,List.of 是一种 Java 9 方法。根据需要构建您的列表)。

您的CommandPipe 类很容易编写:

class CommandPipe {
  int status = success;

  CommandPipe next(IntSupplier supplier) {
    if (status == success) {
      status = supplier.get();
    }
    return this;
  }

  int getResult() { return status; }
}

像你在问题中写的那样调用。

【讨论】:

  • 你没有调用method()
  • 感谢您的回复,以及实现初始目标的另一种方式的建议。我确实认为它实现起来很简单,但是找不到提供如此简单实现的对象,并感到非常惊讶。我在这里问它是为了避免重新发明轮子?
  • 只要你不调用methodList.of(…) 就不能使用 lambda 表达式,因为它缺少目标类型。另一方面,对于这个用例,可变参数方法将消除使用List.of(…) 的需要。 int method(IntSupplier... all) { for(IntSupplier s: all) { int status = s.getAsInt(); if(status != success) return status; } return success; }
  • @EnzoMolion 内置解决方案怎么可能简单?通用工具不了解您的预期语义,即int 结果值和success 的含义。你必须告诉它你想要什么,这就是让它变得不平凡的原因。例如。 Stream.&lt;IntSupplier&gt;of(() -&gt; method0(arg0), () -&gt; method1(arg1) /* etc */) .mapToInt(IntSupplier::getAsInt) .filter(i -&gt; i != success) .findFirst() .orElse(success)
【解决方案4】:

您可以像这样使用可变参数定义静态方法。

public static int pipe(IntSupplier... methods) {
    int success = 0;
    int status = success;
    for (IntSupplier m : methods) {
        status = m.getAsInt();
        if (status != success)
            break;
    }
    return status;
}

int status = pipe(
    () -> method0(arg0),
    () -> method1(arg0),
    () -> method2(arg0),
    () -> method3(arg0),
    () -> method4(arg0));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 2011-09-06
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多