用于执行和操作的解决方案的模式取决于多个条件

时间:2013-09-29 17:37:47

标签: java design-patterns

我们假设有3个操作ops1()ops2()ops3()。客户端可以请求执行那些3的任何组合。例如,

  • 执行(1):应执行ops1()
  • 执行(2):应执行ops2()
  • 执行(1,2):应执行ops1(),如果ops1() 成功,则执行ops2()
  • 执行(1,2,3):执行ops1()并且如果ops1()成功,则执行ops2(),如果两者 ops1()和ops2 ()成功然后执行ops3()

这可以用于n ops()虽然对我而言只有5个。

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

4 个答案:

答案 0 :(得分:1)

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

所以

private List<Callable> ops;

public void perform(int... opNums) {
    try {
        for (int i : opNums) {
            ops.get(i-1).call();
        }
    }
    catch(Exception ex) {
    }
}

答案 1 :(得分: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”的东西是伪代码。

答案 2 :(得分:0)

这样做的方法是

  1. opsX方法和实现此方法的类定义公共接口。
  2. 定义enum以了解应该调用此公共接口的哪个类实现。
  3. 定义一个将作为这些调用的协调器的类。
  4. 此设计的实现可能是

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

答案 3 :(得分:0)

我会将命令模式与Decorator结合使用来解决这个问题。你的命令,如果很多,将包装/装饰彼此:

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