用例是根据前一个是否返回true
来执行一组方法。
例如:
class Test {
boolean method1() {...}
boolean method2() {...}
boolean method3() {...}
...
void callAll() {
if(method1()) {
if(method2() {
if(method3() {
...
}
}
} else {
error();
}
}
}
所有else
都必须有一个if
。
有没有更好的方法来处理这种情况?
答案 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
}
您列出以上所有内容,并调用每个操作,直到发生以下情况之一
failureHandler
。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和链接,它可以是一种性能昂贵的策略。 因此,让我们仅将它们用于其目的。