带返回值的模板方法

时间:2014-11-24 10:58:59

标签: java algorithm template-method-pattern

我有一个算法大纲 - 必须按特定顺序执行的一些逻辑步骤。算法的结果必须是一些数字。当然,这让我想到了使用模板方法模式。这适用于void方法,但问题出现了:算法中的每个步骤都不是void方法,但允许返回一个数字(因此它们是int方法) - 如果一个步骤返回一个非零数字,这个数字是算法执行的结果,如果它是零 - 执行继续下一步。

这可能听起来真的很微不足道,但我仍然觉得它有点像丑陋:

public int algorithm() {
    int resultStep1 = step1();
    if (resultStep1!=0) {
        return resultStep1;
    }
    int resultStep2 = step2();
    if (resultStep2!=0) {
        return resultStep2;
    }
    ...
}

当然step1()step2()等等都是抽象方法,并且在扩展我的相应类中有自己的特定实现。

我想到的另一个想法是使用例外,但正如我们在谈论控制流程一样,这将是一种反模式。

我在这里遗漏了什么,或者这只是我必须写的方式?

2 个答案:

答案 0 :(得分:3)

Java 7

您可以为步骤定义界面:

interface Step {
    int step();
}

然后使用一系列步骤:

ArrayList<Step> steps = new ArrayList<Step>();

像这样迭代它:

public int algorithm() {
    for (Step step : steps) {
        int result = step.step();
        if (result != 0)
            return result;
    }
    return 0;
}

要初始化该列表,可以使用匿名实现类来执行此操作:

steps.add(new Step() {
    @Override
    public int step() {
        return step1(); //or the code directly
    }
});

steps.add(new Step() {
    @Override
    public int step() {
        return step2();
    }
});

或者为每个步骤创建命名良好的实现类:

public class Step1 implements Step {
    @Override
    public int step() {
        // TODO Auto-generated method stub
        return 0;
    }       
}

并添加到列表中:

steps.add(new Step1());
steps.add(new Step2());

在Java8中使用lambda

无需界面。

列表:

ArrayList<Supplier<Integer>> steps = new ArrayList<Supplier<Integer>>();

设定:

steps.add(()-> step1());
steps.add(()-> step2());

算法:

public int algorithm() {
    for (Supplier<Integer> step : steps) {
        int result = step.get();
        if (result != 0)
            return result;
    }
    return 0;
}

答案 1 :(得分:0)

您可以执行以下操作:

if(setResultAndCheckIsNonZero(step1())) {
    return result;
} else if(setResultAndCheckIsNonZero(step2())) {
    return result;
} else if ...

其中:

private int result;

private boolean setResultAndCheckIsNonZero(int x) {
    result = x;
    if(result != 0) 
        return true;
    return false;
}