更换大型案例陈述

时间:2012-02-21 17:54:19

标签: java design-patterns hook

我正在尝试改进使用大量大型语句的Java项目。在使用case语句的情况下,它用于处理具有与之关联的属性的事件。例如:

public void jumpOverWall(int wallID) {
    switch (wallID) {
            case 0:
            case 1213:
            case 2123:
            case 3123:
            case 4123:
    }
}

这些数字是非连续的,并且都需要执行不同的操作 - 例如说"你不能跳过这个墙"或将角色移动到设定位置。案例响应遵循固定模式的情况非常少。我的意思是switch语句不遵循允许代码类似于:

的模式
public void jumpOverWall(int wallID) {
    someArray[1213] = 10;
    someArray[3123] = 20;

    if (playerJumpingSkill > someArray[wallID]) {
            // Do something
    } else {
            sendPlayerMessage("You cannot do this!");
    }
}

因此,我想知道处理这些事件的最佳方式。一个'事件处理程序的整个想法'样式系统是吸引我的东西,但我被困在如何实现它(或更好的解决问题的方法)。有太多的事件' (在我看来)每个人都有一个单独的课程。

是否有挂钩事件的方法/设计?这适用/工作吗?我正在寻找一种轻松挂钩的方法,例如:

hookEvent(1213, new SomeInterface() {
    boolean eventOK() {
        // Do something
        return true;
    }
}

然后这些'钩子'会被检查并打电话吗?

3 个答案:

答案 0 :(得分:4)

命令模式可能是更好的选择。说,你有命令对象实现 接口:

public Interface Command {
      void processEvent(Event e);
}

然后你可以得到一些命令的哈希值,用事件代码键入 - 更具可读性。你甚至可以使用DI容器(弹簧是最流行的,但也有picocontainer或google guice,当然我错过了一些)用于创建命令对象 - 只需使用键作为事件代码注册相应的对象。这将为您保存哈希填充的代码。

它甚至不需要很多条款 - 它可能只是不同配置的实例(取决于您的用例) - 今天没有课堂曝光

答案 1 :(得分:2)

为什么不为每个案例分别设置一个方法?这样,它使您的代码更具可读性。

public void jumpOverWall(int wallID)
{
      switch (wallID) 
        {
        case 0:     methodA(wallID); break; // you could of course have a more descriptive name here.
        case 1213:  methodB(wallID); break; 
        case 2123:  methodC(wallID); break;
        case 3123:  methodD(wallID); break;
        case 4123:  methodE(wallID); break;
        }
}

答案 2 :(得分:1)

由于你的wallIDs确实是纯粹的标识符,并且每个都以不同的方式处理jumpOverWall,所以你确实需要不同的代码。所以我真的为wallIDs使用不同的类。这样,您可以让动态调度进行区分。我不明白你为什么这么想

  

有太多'事件'要有一个单独的类   对于每一个。

由于您无论如何都需要不同的代码,因此使用类不会破坏您的代码。

或者,您可以使用具有常量特定方法实现的枚举

public enum WallID {
1213 { returnType jumpOverWall(Wall wall){ //... 
  } },
3213 { returnType jumpOverWall(Wall wall){ //...
  } },
1332 { returnType jumpOverWall(Wall wall){ //...
  } },

//you can also use better names for your constants ;)

abstract returnType jumpOverWall(Wall wall);
}

你可以在Josh Bloch's Effective Java, 2nd edition,第30项(使用枚举而不是int常量)中详细阅读这是如何工作的,以及为什么你应该更喜欢枚举你的int ID(因为它们真的是纯粹的标识符)。

更新

通过使用这两种方法中的一种而不是int ID和switch语句,您将获得以下几个优势:

  • 更多模块化appraoch,因此更具可读性并遵循SRP
  • 更可重复使用,例如当你想继承一些jumpOverWall行为时
  • 您可以将更多数据与每个常量相关联
  • 如果你愿意的话,你可以为常数提供更多的方法,如果你愿意的话,也可以是常数。
  • 以及我认为最重要的:利用Java的类型系统和动态调度来确保安全。