在方法中重构多个if-else条件

den*_*chr 3 java refactoring conditional

我正在重构我现有的代码.它实际上工作正常,但它有点混乱,多个if-else条件检查一个变量的值,并将第二个变量的值更改为从固定枚举结构中获取的更新值.

else if (var1 == 'valueX')
{
    if (var2 == MyEnum.A)
        var2 = MyEnum.B;
    else if (var2 == MyEnum.B)
        var2 = MyEnum.C;
    else if (var2 == MyEnum.C)
        var2 = MyEnum.D;
    else if (var2 == MyEnum.D)
        var2 = MyEnum.A;
}

else if (....)
{
..similar block of conditionals
}
Run Code Online (Sandbox Code Playgroud)

关于重构和清理这段代码的最佳方法,我有点困惑.你会建议使用开关吗?还是更优雅的东西?

提前致谢!

Car*_*ter 6

重构条件的经典答案是替换条件多态.在这种情况下,如果每个MyEnum都知道它的继承者是什么,你可以简单地说(在'valuex'的情况下:var2 = var2.successor.对于var1 - 如果它可能是一个实现了一个知道如何处理的接口的对象无论你在循环中做什么,每个实现类都知道它应该做什么......好吧,你已经完成了.

更新:

在测试用例中,这是一个花花公子的小继承函数:

public class EnumTest extends TestCase {
    private enum X {
        A, B, C;
        public X successor() {
            return values()[(ordinal() + 1) % values().length];
        }
    };

    public void testSuccessor() throws Exception {
        assertEquals(X.B, X.A.successor());
        assertEquals(X.C, X.B.successor());
        assertEquals(X.A, X.C.successor());
    }
}
Run Code Online (Sandbox Code Playgroud)


Jus*_*eff 5

至少使用J2SE 1.5转发,您可以为枚举提供额外的属性.这意味着您可以用看起来像的东西替换整个if-else字符串

var2 = var1.getNextInSequence();
Run Code Online (Sandbox Code Playgroud)

现在,在这种情况下,看起来您希望该属性是对另一个枚举的引用,这会增加一些皱纹,例如,在初始化它们时无法转发引用枚举,但是可能有一个可行的解决方案这条路.

当属性不是同一枚举的其他实例时,这种事情会起作用:

public enum Animal {
    FOX(4),
    CHICKEN(2),
    WORM(0);

    private int countLegs;

    Animal(int n) {
        countLegs = n;
    }

    public int getLegCount() {
        return countLegs;
    }
    // .. more getters setters etc
}
Run Code Online (Sandbox Code Playgroud)

但是当枚举是自我指涉的时候,你必须要小心你的实例的声明顺序.即,这将有一些问题:

public enum Animal {
    FOX(4, CHICKEN),    // 'CHICKEN' doesn't exist yet
    WORM(0, null),
    CHICKEN(2, WORM);    // this actually will compile

    private int countLegs;
    private Animal eatsWhat;

    Animal(int n, Animal dinner) {
        countLegs = n;
        eatsWhat = dinner;
    }

    public int getLegCount() {
        return countLegs;
    }
    // .. getters, setters, etc
}
Run Code Online (Sandbox Code Playgroud)

因此,如果你需要在枚举之间使用循环引用,你必须工作其他东西,但如果没有,你可以使用这种技术,虽然你可能必须订购你的枚举实例,以使其工作.