Reputation: 3748
I have an outline for an algorithm - some logical steps that has to be performed in a specific order. The result of the algorithm has to be some number. Naturally this led me to the idea of using the template method pattern. This works fine for void
methods but here comes my problem: each of the steps in the algorithm is not a void
method but is allowed to return a number (so they are int
methods) - if a step returns a non-zero number, this number is the result of the algorithm's execution, if it is a zero - the execution continues with the next step.
This might sound really trivial but I just still find it somehow ugly to have something like:
public int algorithm() {
int resultStep1 = step1();
if (resultStep1!=0) {
return resultStep1;
}
int resultStep2 = step2();
if (resultStep2!=0) {
return resultStep2;
}
...
}
Of course step1()
, step2()
and so on are abstract methods and have their own specific implementations in the corresponding classes that extend mine.
The other idea that came to my mind was using exceptions but as we are talking about control flow here this would be an anti-pattern.
Am I missing something here or is this just the way I have to write it?
Upvotes: -1
Views: 679
Reputation:
You can do the following:
if(setResultAndCheckIsNonZero(step1())) {
return result;
} else if(setResultAndCheckIsNonZero(step2())) {
return result;
} else if ...
Where:
private int result;
private boolean setResultAndCheckIsNonZero(int x) {
result = x;
if(result != 0)
return true;
return false;
}
Upvotes: 0
Reputation: 54781
You can define an interface for your steps:
interface Step {
int step();
}
Then use a list of steps:
ArrayList<Step> steps = new ArrayList<Step>();
Iterate over it like so:
public int algorithm() {
for (Step step : steps) {
int result = step.step();
if (result != 0)
return result;
}
return 0;
}
To initialise that list, you can do this using anonymous implementation classes:
steps.add(new Step() {
@Override
public int step() {
return step1(); //or the code directly
}
});
steps.add(new Step() {
@Override
public int step() {
return step2();
}
});
Or create well named implementation classes for each step:
public class Step1 implements Step {
@Override
public int step() {
// TODO Auto-generated method stub
return 0;
}
}
And add to list like this:
steps.add(new Step1());
steps.add(new Step2());
No interface required.
List:
ArrayList<Supplier<Integer>> steps = new ArrayList<Supplier<Integer>>();
Setup:
steps.add(()-> step1());
steps.add(()-> step2());
Algorithm:
public int algorithm() {
for (Supplier<Integer> step : steps) {
int result = step.get();
if (result != 0)
return result;
}
return 0;
}
Upvotes: 3