3

と の 3 つの操作ops1()があるops2()としops3()ます。クライアントは、これら 3 つの任意の組み合わせの実行を要求できます。

  • 実行 (1): 実行する必要がありますops1()
  • 実行 (2): 実行する必要がありますops2()
  • perform(1, 2): ops1() を実行ops1() し、成功した場合は実行する必要がありますops2()
  • perform(1, 2, 3): 実行する必要があり、成功したops1()場合は実行し、ops1() と ops2()の両方が成功した場合は ops3() を実行しますops1()ops2()

これは n ops() まで続けることができますが、私にとってはたったの 5 です。

これを実装するシンプルでエレガントな方法は何ですか? これにはパターンがありますか?

4

4 に答える 4

1

オペレーションをリストに入れ、そのリストで実行するオペレーションを探し、オペレーションが失敗した場合に例外をスローするのはどうですか? 次に、実行メソッドは、完了するか例外が発生するまで、すべてのメソッドを目的の順序で単純に試行および実行できます。

そう

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

この問題には、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
        }
    }
}
于 2013-09-29T19:38:02.007 に答える
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 に答える