是否有一种模式可以根据Java中以前的结果执行一系列方法?

时间:2018-08-06 08:44:32

标签: java

用例是根据前一个是否返回true来执行一组方法。 例如:

class Test {
    boolean method1() {...}
    boolean method2() {...}
    boolean method3() {...}

    ...

    void callAll() {
        if(method1()) {
             if(method2() {
                 if(method3() {
                     ...
                 }
             }
        } else {
            error();
        }
    }
}

所有else都必须有一个if。 有没有更好的方法来处理这种情况?

7 个答案:

答案 0 :(得分:8)

我会这样做:

void callAll(){
    if(method1() && method2() && method3()){
        // all passed
    } else {
        error();    
    }
}

Java short-circuits&&逻辑操作,因此此处先前方法的失败将阻止运行下一个方法。

如果在error()中需要知道哪种方法失败,则可以声明一个错误消息字段以在类中存储信息,并设置与失败相对应的值:

private String errorMessage;

//...

boolean method2() {

    // something went wrong
    errorMessage = "Failed to do method2 stuff";
}

一种更理想的方法是使用Chain of responsibility design pattern并将布尔方法封装在自己的处理程序对象中。但是,这样做将需要对您当前拥有的代码进行更多的重构,并需要有关特定用例的更多信息。

答案 1 :(得分:4)

编写自己的varargs方法很容易做到这一点:

public static void run(Supplier<Boolean>... methods) {
    for (Supplier<Boolean> method : methods) {
        if (!method.get()) return;
    }
}

样品用量:

run(this::method1, this::method2, this::method3);

答案 2 :(得分:1)

您也可以对这种类型的Thin使用某种形式的Observable模式。在大多数正常情况下,实现它似乎有些愚蠢,但如果有很多这样的方法,那么这是一种将代码与控制结构分离的好方法。请注意,ObservableBoolean是一个Android类,但此处仅显示逻辑:

    ObservableBoolean a = new ObservableBoolean();
    ObservableBoolean b = new ObservableBoolean();

    public void call() {
        a.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(android.databinding.Observable sender, int propertyId) {
                method2();
            }
        });
        b.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(android.databinding.Observable sender, int propertyId) {
                //..you end the "chain" here
            }
        });
        method1();
    }

    void method1() {
        if(true) {
            a.set(true);
        }
        else {
            b.set(false);
        }
    }

    void method2() {
        if(true) {
            b.set(true);
        }
        else {
            b.set(false);
        }
    }

答案 3 :(得分:1)

您定义一个类,该类包含一个动作(调用方法之一)并具有相应的失败处理程序( if 调用的else块)

public static class ActionWithFailureHandler {
    private Supplier<Boolean> action;
    private Runnable failureHandler;

    public ActionWithFailureHandler(Supplier<Boolean> action, Runnable failureHandler) {
        this.action = action;
        this.failureHandler = failureHandler;
    }
    //Getters for the instance variables

}

您列出以上所有内容,并调用每个操作,直到发生以下情况之一

  1. 其中一个操作失败(即,其中一个方法返回false)。在这种情况下,您需要执行与该操作相对应的failureHandler
  2. 所有动作均通过。在这种情况下,请执行successHandler(当所有方法都返回true时执行的逻辑)。

private static void callAll(List<ActionWithFailureHandler> actionWithFailureHandlers, Runnable successHandler) {
    actionWithFailureHandlers.stream()
            .filter(actionWithFailureHandler -> !actionWithFailureHandler.getAction().get())
            .findFirst() //Find first failing action
            .map(ActionWithFailureHandler::getFailureHandler)
            .orElse(successHandler)
            .run(); //You might be running either the successHandler or the failureHandler for the first failed action
}

驱动程序代码:

public static void main(String[] args) {
    Test test = new Test();
    List<ActionWithFailureHandler> actionWithFailureHandlers = com.google.common.collect.ImmutableList.of(
            new ActionWithFailureHandler(test::method1, () -> System.out.println("Method 1 returned false")),
            new ActionWithFailureHandler(test::method2, () -> System.out.println("Method 2 returned false")),
            new ActionWithFailureHandler(test::method3, () -> System.out.println("Method 3 returned false"))

        );
    callAll(actionWithFailureHandlers, () -> System.out.println("All returned true"));
}

答案 4 :(得分:1)

我使用这种技术-尽管有些人会觉得奇怪。

boolean method1() {
    System.out.println("method1");
    return true;
}

boolean method2() {
    System.out.println("method2");
    return false;
}

boolean method3() {
    System.out.println("method3");
    return true;
}

void callAll() {
    boolean success = method1();
    success = success ? method2() : success;
    success = success ? method3() : success;
    if (success) {
        System.out.println("Success");
    } else {
        System.out.println("Failed");
    }
}

答案 5 :(得分:1)

我建议您使用RX方法,对于rxjava,它应该看起来像

public boolean test1() {
    Log.d("TESTIT", "test1 called");
    return true;
}

public boolean test2() {
    Log.d("TESTIT", "test2 called");
    return true;
}

public boolean test3() {
    Log.d("TESTIT", "test3 called");
    return false;
}

public boolean test4() {
    Log.d("TESTIT", "test4 called");
    return true;
}

public boolean elseMethod(boolean result) {
    if (result) return true;
    else {
        Log.d("TESTIT", "ELSE");
    }
    return false;
}

public void chainedCallback() {
    Observable.just(test1())
            .filter(this::elseMethod)
            .flatMap(aBoolean -> Observable.just(test2()))
            .filter(this::elseMethod)
            .flatMap(aBoolean -> Observable.just(test3()))
            .filter(this::elseMethod)
            .flatMap(aBoolean -> Observable.just(test4()))
            .filter(this::elseMethod)
            .subscribe();
}

呼叫chainedCallback()的请求将会打印

test1 called
test2 called
test3 called
ELSE

答案 6 :(得分:-1)

Exception首先出现在我的脑海中,但是请参阅下面的链接以了解有关其效果的更多信息。

原始答案。我会的。

public class MyException extends Exception
{
}
public void doAll()
{
     try
     {
          method1();
          method2();
          method3();
     }catch (MyException e)
     {
            error();
      }
}

我们假设method1,method2和method3在失败时会抛出MyException。

尽管它不适合您的问题,但使用Exception是一个很好的模式。

public class Helper
{
    public Helper(Method m)
    {
          this.method=m;
     }
     public void Do() throws MyException
     {
          if(method.invoke()==false)
                throw new MyException ();
      }
} 

使用此类,

public void doAll()
    {
         Helper [] helpers={new Helper(this::method1), new Helper(this::method2), new Helper (this::method3)};

         try
         {
              for(Helper helper:helpers)
              {
                     helper.Do();
               }
         }catch (MyException e)
         {
                error();
          }
    }

但是

根据 @dilix the comment和链接,它可以是一种性能昂贵的策略。 因此,让我们仅将它们用于其目的。