Java中嵌套switch语句的替代方案

21

今天我写了一个方法,其中使用了嵌套的switch语句,代码看起来相当干净简洁,但是我被告知,嵌套的switch语句通常不是最好的选择,因为随着你添加更多的switch语句,它们可能会变得混乱。以下是我代码的示例:

EnumOne enumOne;
EnumTwo enumTwo = null;
EnumTwo enumThree = null;

switch (enumOne) {
   case CASE_ONE:

      switch (enumTwo){
         case A: enumTwo = EnumTwo.B; break;
         case C: enumTwo = EnumTwo.D; break;
         default: break;
      }

      switch (enumThree) {
         case AA: enumThree = EnumTwo.BB; break;
         case CC: enumThree = EnumTwo.DD; break;
         default: break;
      }

      break;

   case CASE_TWO:
   case CASE_THREE:

      switch(EnumTwo) {
         default: break;
      }

      switch (enumThree) {
         case AA: enumThree = EnumTwo.XX; break;
         case CC: enumThree = EnumTwo.YY; break;
         default: break;
      }

      break;

   default:
      break;
}

那么我的问题本质上是,有没有适合替代这些开关语句的方法?


1
你是用它来做什么的?建模状态机吗? - flup
2
所以 enumTwo 的值是根据枚举 one、two 和 three 的值而定的?为什么不在 enumTwo 中编写一个方法来返回新值呢?这类似于状态模式。 - Boris the Spider
大量嵌套的 switch / if 语句的使用通常显示出设计缺陷,特别是在面向对象的语言中,应该使用它们提供的功能。 - gersonZaragocin
3个回答

24
  1. 因为使用大量的开关语句会变得难以阅读。
  2. 每当出现新情况时,我们都必须修改代码并添加一个CASE。

在这种情况下,我们可以考虑使用多态性。

我将提供一个简单的类让您了解。 假设一个之前用开关语句的类。

class Test
{ 
    Animal a;
    public Test(Animal a)
    { 
        this.a=a;
    }

    public moveThisAnimal()
    {
        switch(this.a)
        {
            case fish:
            System.out.println("swim");
            break;

            case dog:
            System.out.println("walk");
            break;

            case bird:
            System.out.println("fly");
            break;
        }
    }
}

现在,我们将使用多态逻辑替换这些开关。

Interface Animal
{
    String move();
} 

Class Dog implements Animal
{
    public String move()
    {
        return "walk";
    }
}


Class Bird implements Animal
{
    public String move()
    {
        return "fly";
    }
}


Class Fish implements Animal
{
    public String move()
    {
        return "swim";
    }
}

现在我们有了一个不含switch case的Test类

class Test
{ 
    Animal a;
    public Test(Animal a)
    { 
        this.a=a;
    }
    public moveThisAnimal()
    {
        System.out.println(this.a.move()); // all switch case statements removed 
    }
}

即使我们不得不添加更多情况,我们只需要添加实现,这里不需要更改。

检查您的完整代码并查看是否可以执行。


1
这是一个非常有用的答案,但我发现其中存在一些问题。“Class”应该是小写的,每个动物的移动重写也应该是小写的。此外,第一个示例将它们显示为System.out.println,但在“正确”的方式中并不是这样呈现的。我是这样做的public void moveThisAnimal() { System.out.println(this.a.move()); // 所有switch case语句都被删除了 } public static void main (String[] args) { Dog d = new Dog(); test t = new test(d); t.moveThisAnimal(); } - XaolingBao

15

我建议您用一个过程调用来代替每个嵌套的switch语句,然后执行嵌套的switch代码。

可像这样编写:

    EnumOne enumOne;
    EnumTwo enumTwo = null;
    EnumTwo enumThree = null;

    switch (enumOne)
    {
       case CASE_ONE:

          nested_switch1();

       case CASE_TWO:
       case CASE_THREE:

          nested_switch2();

          break;

       default:
          break;
    }

    nested_switch1() {
          switch (enumTwo)
          {
             case A:
                enumTwo = EnumTwo.B;
                break;
             case C:
                enumTwo = EnumTwo.D;
                break;
             default:
                break;
          }

          switch (enumThree)
          {
             case AA:
                enumTwo = EnumTwo.BB;
                break;
             case CC:
                enumTwo = EnumTwo.DD;
                break;
             default:
                break;
          }

          break;
    }

nested_switch2() {
          switch(EnumTwo)
          {
             default:
                break;
          }

          switch (enumThree)
          {
             case AA:
                enumTwo = EnumTwo.XX;
                break;
             case CC:
                enumTwo = EnumTwo.YY;
                break;
             default:
                break;
          }
}

一个基本的面向对象编程原则。 - Lendl Leyba

6
如果您有整数X和Y,并且需要同时打开它们,您可以以一种明确的方式将它们组合起来并打开组合。例如,如果y < 10:
switch (x*10+y)
{
case 0: // x == y == 0
case 1: // x ==0, y == 1
///
case 10: // x == 1, y == 0
case 11: // x == y == 1
//
}

这是最简单和最好的方法。 - Napolean
1
这假设顺序不重要。x10+y=y10+x。这可能导致误报。 - Japheth Ongeri - inkalimeva
1
@inkalimeva 这个示例做出了这种假设。而一般的技术则没有。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接