Reputation: 80192
Let us say there are 3 operations ops1()
, ops2()
and ops3()
. The client can request to execute any combination of those 3. For e.g.
ops1()
ops2()
ops1()
is successful then execute ops2()
ops1()
and if ops1()
is successful then execute ops2()
and if both ops1() and ops2() are successful then execute ops3()This can go on for n ops() though for me its just 5.
What is the simple and elegant way of implementing this? Is there a pattern for this?
Upvotes: 3
Views: 144
Reputation: 1881
I would use the command pattern in combination with the Decorator for this problem. Your commands, when many, will be wrapping/decorating each others :
public class Command{
private Command subCommand;
public Command(Command subCommand){
this.subCommand=subCommand;
}
public Command(){};
public Command addSubCommand(Command command)
{
subCommand=command;
return command;
}
//A Command class is decorating itself
//by adding a behavior over its subcommand
public void execute() throws CommandExecutionException {
executeImpl();
if(subCommand!=null) subCommand.execute();
}
protected void executeImpl() throws CommandExecutionException {
//To be overiden
}
}
public class CommandA extends Command{
private CommandAExecutor ops1Handler;
protected void executeImpl(){
ops1Handler.ops1();
}
}
//....
public class CommandN extends Command{
private CommandNExecutor opsNHandler;
protected void executeImpl(){
opsNHandler.opsN();
}
}
public class Tester{
public static void main(String[] args){
Command commandA = new CommandA(new CommandAExecutor());
Command commandB = new CommandB(new CommandBExecutor());
Command commandN = new CommandN(new CommandNExecutor());
//The order here is A, N, B
commandA.addSubCommand(commandN).addSubCommand(B);
try{
commandA.execute();
}catch(CommandExecutionException e){
//...failure
}
}
}
Upvotes: 0
Reputation: 27103
How about you put your ops in a list, look the operations to perform up in that list, and let the operations throw an exception if they fail? Then the perform method can simply try and perform all methods in the desired order until it's done or an exception occurs.
So
private List<Callable> ops;
public void perform(int... opNums) {
try {
for (int i : opNums) {
ops.get(i-1).call();
}
}
catch(Exception ex) {
}
}
Upvotes: 1
Reputation: 85799
An approach for this would be
opsX
methods and the classes that implement this method.enum
to know which class implementation of this common interface should be called.An implementation of this design may be
interface CommonOps {
boolean ops();
}
class Ops1 implements CommonOps {
@Override
public boolean ops() {
//...
}
}
class Ops2 implements CommonOps {
@Override
public boolean ops() {
//...
}
}
//and on...
enum OpsOrder {
OPS1,
OPS2,
OPS3
//... and on
;
}
class Orchestrator {
public boolean executeOps(OpsOrder order) {
switch (order) {
case OPS1:
return new Ops1().ops();
case OPS2:
return new Ops2().ops();
//...
default:
throw new IllegalArgumentException("Not supported.");
}
throw new UnsupportedOperationException("This exception should never be reached.");
}
public boolean orchestrate(OpsOrder ... orders) {
for (OpsOrder order : orders) {
if (!executeOps(orders)) {
return false;
}
}
return true;
}
}
This can be even more generic by having a factory of CommonOps
class implementations so Orchestrator
should not know which CommonOps
will be called:
final class CommonOpsFactory {
private CommonOpsFactory () { }
public static CommonOps create(OpsOrder order) {
switch (order) {
case OPS1:
return new Ops1();
case OPS2:
return new Ops2();
//...
default:
throw new IllegalArgumentException("Not supported.");
}
}
}
class Orchestrator {
public boolean executeOps(OpsOrder order) {
return CommonOpsFactory.create(order).ops();
}
public boolean orchestrate(OpsOrder ... orders) {
for (OpsOrder order : orders) {
if (!executeOps(orders)) {
return false;
}
}
return true;
}
}
Upvotes: 0
Reputation: 18901
I see a solution somewhat like this:
public void perform(int... ops) {
for(int i : ops) {
switch(i) {
case 1:
//...
// if(taskFailed) return;
break;
case 2:
//...
// if(taskFailed) return;
break;
case 3:
//...
// if(taskFailed) return;
break;
// so on for all 5
}
}
}
It's just the general idea, not tested if the syntax is entirely correct.
the "taskFailed" thing is a pseudocode.
Upvotes: 0