3

假设有 3 个操作ops1()和。客户端可以请求执行这 3 个的任意组合。例如ops2()ops3()

  • perform(1):应该执行ops1()
  • perform(2):应该执行ops2()
  • perform(1, 2):应该执行 ops1(),如果ops1() 成功则执行ops2()
  • perform(1, 2, 3):应该执行ops1(),如果ops1()成功则执行ops2(),如果ops1 () 和 ops2()都成功则执行 ops3()

这可以持续 n ops() 虽然对我来说只有 5 个。

实现这一点的简单而优雅的方式是什么?有这种模式吗?

4

4 回答 4

1

您如何将您的操作放在一个列表中,在该列表中查找要执行的操作,如果操作失败则让操作抛出异常?然后 perform 方法可以简单地尝试按所需顺序执行所有方法,直到完成或发生异常。

所以

private List<Callable> ops;

public void perform(int... opNums) {
    try {
        for (int i : opNums) {
            ops.get(i-1).call();
        }
    }
    catch(Exception ex) {
    }
}
于 2013-09-29T19:45:08.363 回答
0

一种方法是

  1. opsX为方法和实现该方法的类定义一个通用接口。
  2. 定义一个enum来知道应该调用这个公共接口的哪个类实现。
  3. 定义一个类,作为这些调用的协调器。

这种设计的实现可能是

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;
    }
}

CommonOps通过拥有一个类实现工厂,这可以更加通用,所以Orchestrator不应该知道哪个CommonOps会被调用:

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;
    }
}
于 2013-09-29T18:06:44.393 回答
0

我看到一个有点像这样的解决方案:

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
        }

    }

}

这只是一般的想法,没有测试语法是否完全正确。

“taskFailed”是一个伪代码。

于 2013-09-29T17:59:41.143 回答
0

我会结合使用命令模式和装饰器来解决这个问题。你的命令,当很多时,将相互包装/装饰:

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
        }
    }
}
于 2013-09-29T19:38:02.007 回答