Java 重构一系列方法

Java 重构一系列方法,java,java-8,refactoring,optional,Java,Java 8,Refactoring,Optional,我有一系列的方法,我需要按顺序运行,在下一步中使用每个方法的结果作为参数。但是,在调用下一个方法之前,我还要检查每个方法的结果是否为“好”(如果为“坏”,那么我会提前退出该方法。如果方法不成功,则返回空的可选 我是否可以执行重构来改进代码?责任链感觉有点过火了 private boolean isSequenceSuccessful() { Optional<byte[]> result1 = doSomething(); if (!result1.isPresent())

我有一系列的方法,我需要按顺序运行,在下一步中使用每个方法的结果作为参数。但是,在调用下一个方法之前,我还要检查每个方法的结果是否为“好”(如果为“坏”,那么我会提前退出该方法。如果方法不成功,则返回空的
可选

我是否可以执行重构来改进代码?责任链感觉有点过火了

private boolean isSequenceSuccessful() {
  Optional<byte[]> result1 = doSomething();

  if (!result1.isPresent()) {
    return false;
  }

  Optional<byte[]> result2 = doAnotherThing(result1.get());

  if (!result2.isPresent()) {
    return false;
  }

  Optional<byte[]> result3 = doSomethingElse(result2.get());

  if (!result3.isPresent()) {
    return false;
  }

  return doMoreStuff(result3.get());
}
私有布尔值isSequenceSuccessful(){
可选结果1=doSomething();
如果(!result1.isPresent()){
返回false;
}
可选的result2=doAnotherThing(result1.get());
如果(!result2.isPresent()){
返回false;
}
可选的result3=doSomethingElse(result2.get());
如果(!result3.isPresent()){
返回false;
}
返回doMoreStuff(result3.get());
}

我不想使用异常来控制方法的流程,因为这是一种代码味道(我希望有时会得到“糟糕”的结果)。

您可以使用
map
方法:

private boolean isSequenceSuccessful() {
  Optional<byte[]> result = doSomething().map(this::doAnotherThing)
                                         .map(this::doSomethingElse);
  if (result.isPresent()) return doMoreStuff(result.get());
  else return false;
}
私有布尔值isSequenceSuccessful(){
可选结果=doSomething().map(this::doNotherthing)
.map(此::doSomethingElse);
if(result.isPresent())返回domarestuff(result.get());
否则返回false;
}

您可以使用
Optional
和映射将其写得更短:

private boolean isSequenceSuccessful() {
    return Optional.of(doSomething())
            .flatMap(result1 -> doAnotherThing(result1))
            .flatMap(result2 -> doSomethingElse(result2))
            .map(result3 -> doMoreStuff(result3))
            .orElse(false);
}
或者使用更短的方法引用:

private boolean isSequenceSuccessful2() {
    return Optional.of(doSomething())
            .flatMap(this::doAnotherThing)
            .flatMap(this::doSomethingElse)
            .map(this::doMoreStuff)
            .orElse(false);
}
这取决于您喜欢什么。如果您想保留中间结果变量,请使用lambda版本

由于方法
doAnotherThing
doSomethingElse
确实返回一个
Optional
Optional.flatMap
需要继续映射。否则,您可以将这些方法的返回类型更改为返回
字节[]
单独使用。然后您将仅使用
optional.map
,这将更加一致


只有在
可选
中存在一个值时,才会执行映射。如果可以应用所有映射,则返回最后一个的值作为结果。否则处理将快速失败,并绕过所有剩余映射到最后一个语句
orElse
,返回其值。这是
false
g到您的代码。

使用
可选::flatMap

private boolean isSequenceSuccessful() {
    Optional<Boolean> result = doSomething()
        .flatMap(this::doAnotherThing)
        .flatMap(this::doSomethingElse)
        .map(this::doMoreStuff);
    return result.isPresent() ? result.get() : false;
}
私有布尔值isSequenceSuccessful(){
可选结果=剂量测定法()
.flatMap(this::doNotherthing)
.flatMap(this::doSomethingElse)
.map(this::doMoreStuff);
返回result.isPresent()?result.get():false;
}

看看模板模式,我有时称之为比萨饼模式,因为它类似于制作比萨饼。(例如CreateRough()、PutComponents()、bake()、package()、deliver())。这可能适用于您的情况。有几个示例和实现,但请选择最适合您的示例。在上面的示例中,我将创建一个抽象类并创建具体的类/实现。示例为您提供了一个想法:

public abstract class SequenceChecker {

    // ...

    public boolean isSequenceSuccessful() {
        Optional<byte[]> result1 = doSomething();
        Optional<byte[]> result2 = doAnotherThing(result1);
        Optional<byte[]> result3 = doSomethingElse(result2);
        return doMoreStuff(result3);
    }

    protected abstract boolean doMoreStuff(Optional<byte[]> result);

    protected abstract Optional<byte[]> doSomethingElse(Optional<byte[]> result);

    protected abstract Optional<byte[]> doAnotherThing(Optional<byte[]> result);

    protected abstract Optional<byte[]> doSomething();

    // ...
}
公共抽象类SequenceChecker{
// ...
公共布尔值isSequenceSuccessful(){
可选结果1=doSomething();
可选结果2=doAnotherThing(结果1);
可选结果3=doSomethingElse(结果2);
返回doMoreStuff(结果3);
}
受保护的抽象布尔domorseuff(可选结果);
受保护的抽象可选剂量表(可选结果);
受保护的抽象可选DoNotherthing(可选结果);
受保护的抽象可选剂量测量();
// ...
}

使用
Optional
然后在最后捕获一个潜在的
NullPointerException
而不是使用
Optional
检查是否存在一个值的附加值是什么?@LuCio哦,我想它会返回一个空的可选值。我已经更新了答案。谢谢!我最后通过te[]
因此,根据您的建议,我使用的是plain
.map()
s。它绝对更简单,而且由于您在
中链接中间结果是成功的
,因此子方法不需要知道它是如何在那里完成的,也就是通过
可选的