【问题标题】:Design Pattern replacing nested switch/ifelse替换嵌套 switch/ifelse 的设计模式
【发布时间】:2011-11-08 09:32:00
【问题描述】:

我正在使用 Java,我已经看到了很多设计模式并试图解决我的问题,但不知何故我就是找不到好的那个。

这些是我收到的示例数据包:

{String robot, String action, int duration}
{"Humanoid", "Forward", 2}
{"Humanoid", "Backward", 5}
{"Snatcher", "Grab"}

这是我现在的代码:

if "humanoid" {
    if "forward" {
        humanoid.forward(duration);
    }
    if "backward" {
        humanoid.backward(duration);
    }
    ...
}else if "snatcher" {
    if "forward" {
        snatcher.forward(duration);
    }
    if "grab" {
        snatcher.grab();
    }
}
elseif ...

动态执行此操作的最佳方法是什么?

我不想每次我想在嵌套的 ifelse 中添加一个具有所有可能功能的新机器人时都向我的 ifelse 添加一个节点。

谢谢!

编辑

与此同时,我被要求将问题分成两部分。机器人类型之间的切换将在别处完成,我将使用策略模式根据机器人在不同类型的动作之间切换。

不管怎样,谢谢大家的回答!我相信它会在其他时间或对其他人有用!

【问题讨论】:

  • humanoidsnatcher 是什么?它们是同一个类的实例,还是共享一个共同的超类,还是完全不相关?

标签: java design-patterns nested switch-statement


【解决方案1】:

您可以使用调度程序,以下是伪代码,无法编译:

interface Executor { public void execute(); }
class RobotAction {
    String robot;
    String action;
    Executor executor;
}

那么你有一些设置:

list.add(new RobotAction("Humanoid", "Forward", new Executor() { public void execute() { humanoid.forward(5) }));
list.add(new RobotAction("Humanoid", "Backward", new Executor() { public void execute() { humanoid.backward(2) }));
list.add(new RobotAction("Snatcher", "Grab", new Executor() { public void execute() { snatcher.grab() }));

那么你的方法就变成了:

public void dispatch(String robot, String action) {
    for (RobotAction robotAction : list) {
         if (robot.equals(robotAction.robot) && action.equals(robotAction.action)) {
             robotAction.execute();
         }
    }
}

所以要添加一个新动作,你需要在列表中添加一些东西。更好的方法是从 RobotAction -> Executor 获取地图;这需要你实现 equals & hashCode。

【讨论】:

    【解决方案2】:

    很难知道您到底想用有限的信息做什么,但是如果您从某个地方收到一堆“操作请求”并且需要不同类别的对象以不同的方式处理它们,您可以做这样的事情:

    interface IActionHandler{
      void HandleAction(Action action);
    }
    
    class Humanoid: IActionHandler{
      void HandleAction(Action action){
        switch(action.ActionType){
           ActionType.Forward: Forward();
          ......
        }
      }
    ...
    }
    
    class Catcher: IActionHandler{
      void HandleAction(Action action){
        switch(action.ActionType){
           ActionType.Grab: Grab();
          ......
        }
      }
    ...
    }
    
    class MainActionReceiver{
      ReceiceActionRequest(Action action){
        GetActioner(action.Actioner).HandleAction(action);
      }
    
      IActionHander GetActioner(string actioner){
        if (actioner == "Humanoid"){
          return humanoidObject;
        }
        return catcherObject;
      }
    }
    

    请原谅半 C# 风格 - 这是我今天的工作。

    如果您想避免在 HandleAction 函数中使用 switch 语句,您可以创建 ActionExecuter 类来实际执行如下操作:

    Interface IExecuter<T>{   
      bool CanExecute(Action action)
      void Execute(T owner, Action action); 
    }
    

    然后有

    class ForwardExecuter<Humanoid>{
      bool CanExecute{
        return action.ActionType == forward;
      }
    
      Execute(Humaniod owner, Action action){
        owner.Forward();
      }
    }
    

    向类注册可用的ActionExecuters,然后在Handler中循环寻找可以执行动作的Executer,然后将其传递给执行者。

    class Humanoid: IActionHandler{
      void HandleAction(Action action){
        foreach (IExecuter in executers){
          if (executer.CanExecute(action)){
            executer.Execute(this, action);
          }
        }
      }
    ...
    }
    

    这很可能对你正在做的事情来说太过分了,但是你所有的动作和动作执行器都干净地封装在它们自己的类中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-24
      • 2021-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-27
      • 1970-01-01
      相关资源
      最近更新 更多