2013-09-29 26 views
3

讓我們假設有3個操作ops1(),ops2()ops3()。客戶可以請求執行這些的任意組合。取決於多個條件的執行和操作的解決方案模式

  • 執行(1):應執行ops1()
  • 執行(2):應執行ops2()
  • 執行(1,2):應執行OPS1(),並且如果ops1()是成功的,則執行ops2()
  • 執行(1,2,3):應執行ops1()並且如果ops1()成功,則執行ops2()和如果既 OPS1()和OPS2()是成功的,則執行 OPS3()

這可以去當n OPS()雖然對我來說它只是5

什麼是實現這個簡單而優雅的方式?有這樣的模式嗎?

+0

如果不成功,它拋出異常? –

+1

我可以看到這是一個責任鏈 –

+0

@SotiriosDelimanolis是的。每個操作都可以拋出異常,客戶端會收到一個錯誤,指出執行失敗。 –

回答

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」是一個僞代碼。

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

你如何處理你必須執行ops1()和ops2() –

+0

@Pangea的情況如果你調用'Orchestrator#orchestrate(OpsOrder.OPS1,OpsOrder.OPS2)',那麼它將執行'Ops1()。ops ()',然後'Ops2()。ops()'。 –

+0

'OpsOrder'這個名字似乎有點不合適,因爲它不代表操作順序。而是作爲可用的不同操作的標識。但是我對使用'...'量詞的命名規則不熟悉,對此有何看法? – atomman

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

你怎麼樣把你的OPS在列表中,查找操作,以在該列表中執行起來,並讓操作拋出,如果他們異常失敗?然後,執行方法可以簡單地按照所需的順序嘗試和執行所有方法,直到完成或異常發生。

所以

private List<Callable> ops; 

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