删除枚举中的开关语句

时间:2013-10-28 20:29:01

标签: java enums switch-statement

对于竞技场游戏,我有一个可能的游戏类型的枚举。这些游戏类型中的每一个都有一个与之关联的变体列表,以及每个枚举的2个类,用于侦听事件和处理配置值。目前,我从枚举构造这些侦听器和配置加载器。在这样做时,我必须使用switch语句。以下方法从枚举值中获取侦听器。

public GameListener getListener(CustomGame cg) {
    switch(this) {
    case Slayer:
        return new SlayerListener(cg);
    case Capture_The_Flag:
        return new CaptureTheFlagListener(cg);
    case Oddball:
        return new OddballListener(cg);
    case HeadHunter:
        return new HeadHunterListener(cg);
    case King_Of_The_Hill:
        return new KOTHListener(cg);
    default:
        return null;
    }
}

配置存在类似的代码。我知道使用抽象方法我可以删除switch语句,但我想知道是否有更简单的方法。我试图让我的枚举采用2种类型的参数,但我无法使其工作,我将无法用它们构建。一种选择是传入Class<T>并通过反射构建对象。

这个类中有另一个方法,每个枚举的布局都有很多不同,我认为最好的选择是抽象方法,但我觉得这里有一个更简单的解决方案。

3 个答案:

答案 0 :(得分:4)

这有点冗长,但您可以直接在枚举类型上提供工厂方法:

public enum GameType {
  SLAYER {
    @Override
    public GameListener getListener(CustomGame cg)
      return new SlayerListener(cg);
    }
  },
  // ... similarly for other GameListener types

  public abstract GameListener getListener(CustomGame cg);
}

关于此解决方案的好处是,如果不定义GameType方法的实现,现在无法创建新的getListener()

答案 1 :(得分:1)

这是一种工厂方法,我认为在这种情况下使用开关是完全有效的。另一种方法是创建Listeners的继承层次结构,并声明对侦听器的(可能是抽象的)超类的引用,而在运行时,您将为引用实例化正确的侦听器。也许是太麻烦了,但更多的是面向对象的。这是需要大量课程的完美OO设计与充满switch语句的代码之间的权衡,请选择。

答案 2 :(得分:0)

如果性能无关紧要,您可以使用这样的通用GameListener Getter:

public Listener getListener( CustomGame cg ) {
    // implement some smart way to find your listener implementation here...
    Class<? extends Listener> clzz = Class.forName( this.getClass().getPackage() + "." + name() );
    Listener ret = clzz.newInstance();
    ret.setCustomGame(cg);
    return ret;
}

这不需要维护,也不需要枚举中的特殊参数。但是,当然,它会将枚举名称直接链接到创建的类名称,这可能不是所需的约束。