替换嵌套 switch/ifelse 的设计模式

发布于 2024-12-14 09:09:59 字数 778 浏览 2 评论 0原文

我正在使用 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 添加节点。

谢谢!

编辑

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

无论如何,感谢所有的答案!我确信它下次或对其他人会有用!

I'm working in Java and I've seen a lot of design patterns and tried to fit my problem in it but somehow I just can't find the good one.

These are example packets I receive:

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

This is my code now:

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

What's the best way to do this dynamically?

I don't want to add a node to my ifelse everytime I'd like to add a new robot with all of its possible functions in the nested ifelse.

Thanks!

EDIT

In the mean time I've been asked to split the problem in two parts. The switch between types of robots will be done elsewhere and I'll use Strategy Pattern to switch between the different types of actions depending on the robot.

Anyway, thanks for all the answers! I'm sure it will be useful another time or for somebody else!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘逸的'云 2024-12-21 09:09:59

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

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 -> 获取地图。执行人;这需要你实现 equals &哈希码。

You could use a dispatcher, the following is pseudo code, doesn't compile:

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

then you have some setup:

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

then your method becomes:

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

So to add a new action, you add something to the list. A better method would be to have a map from RobotAction -> Executor; this would require you to implement equals & hashCode.

橪书 2024-12-21 09:09:59

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

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,然后在处理程序中循环查找可以执行的执行器动作,然后将其传递给执行者。

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

对于您正在做的事情来说,这很可能有点矫枉过正,但是您可以将所有操作和操作执行器干净地封装在它们自己的类中。

Hard to know what it is you're trying to do exactly with the limited information but if you're getting a bunch of "action requests" from somewhere and need to have different classes of object process them in different ways you could do something like this:

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

Excuse the semi-C# style - it's what I'm working in today.

If you wanted to avoid the switch statement in the HandleAction functions you could create ActionExecuter classes to actually execute the actions like this:

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

Then have

class ForwardExecuter<Humanoid>{
  bool CanExecute{
    return action.ActionType == forward;
  }

  Execute(Humaniod owner, Action action){
    owner.Forward();
  }
}

register the available ActionExecuters with the classes and then loop through the in the Handler looking for an Executer that can execute the action and then pass this to the executer.

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

That's quite possibly overkill for what you are doing, but you then have all your actions and action executers cleanly encapsulated in their own classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文