设计模式替换嵌套开关/ ifelse

时间:2011-11-08 09:32:01

标签: java design-patterns nested switch-statement

我在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中添加一个节点。

谢谢!

修改

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

无论如何,感谢所有答案!我相信它会在另一个时间或其他人有用!

2 个答案:

答案 0 :(得分:4)

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

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获得一张地图 - >遗嘱执行人;这需要你实现等于&哈希码。

答案 1 :(得分: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);
      }
    }
  }
...
}

这对你正在做的事情来说可能有些过分,但你可以将所有的行动和行动执行者干净地封装在他们自己的班级中。