I would use Composite and Command.
interface CalculateCommand {
public void calculate(CalculateContext context);
}
Now create an implementation for each attempt you want.
Next create a CompositeCommand -- here is an outline (you will need to fill in the blanks)
public class CompositeCalculateCommand implements CalculateCommand {
CompositeCalculateCommand(List<CompositeCommand> commands) {
this.commands = commands; // define this as a field
}
public void calculate(CommandContext context) {
for (CalculateCommand command : commands) {
try {
command.calculate(context);
} catch(RuntimeException e) {
this.exceptions.add(e) // initialize a list to hold exceptions
}
if (context.hasResult) return; // break
}
// throw here. You didn't success since you never saw a success in your context. You have a list of all exceptions.
}
}
finally use it like
CalculateCommand allCommands = new CompositeCalculateCommand(someListOfCommands);
allCommands.calculate(someContextThatYouDefine);
// results now on context.
Note each command implementation is testable on its own, so this is very maintainable. If you need to add calculations, you simply define a new type of CalculateCommand
, so this is extensible. It will also play well with dependency injection. Note I define a CommandContext object so different commands can take different types of stuff (put in a context).