Pergunta

Eu estou no processo de refatoração meu código existente. Ele realmente funciona muito bem, mas é um pouco confuso com vários if-else condicionais verificando o valor de uma variável e altere o valor de uma segunda variável para um valor atualizado tirado de uma estrutura enumeração fixo.

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
}

Estou um pouco confuso quanto ao que é a melhor maneira de refatorar e clean-up este código. Que você sugere o uso de uma chave, talvez? Ou algo mais elegante?

Agradecemos antecipadamente!

Foi útil?

Solução

Pelo menos com J2SE 1.5 para a frente, você pode dar atributos extras enums. Isto significa que você pode ser capaz de substituir toda essa cadeia de if-else com algo que se parece com

var2 = var1.getNextInSequence();

Agora, neste caso, parece que você gostaria que o atributo a ser uma referência para outro enum, que acrescenta alguns rugas, por exemplo, você pode enums referência não para a frente quando você inicializa-la, mas não pode ser um viável solução para você desta forma.

Quando os atributos não são outros exemplos do mesmo enum, esse tipo de coisa vai funcionar:

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
}

Mas quando o enum é auto-referencial, você tem que ter cuidado com a ordem de declaração de suas instâncias. Ou seja, isso vai ter alguns problemas:

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
}

Então se você tivesse necessidade de um conjunto circular de referências entre os enums, você teria que trabalhar mais alguma coisa, mas se não, você poderia usar esta técnica, embora você pode ter que encomendar suas instâncias de enumeração apenas para torná-lo trabalho.

Outras dicas

A resposta clássica para condicionais refatoração é Substituir condicional com Polimorfismo . Neste caso, se cada um de MyEnum sabia o que seu sucessor fosse, você poderia simplesmente dizer (no caso 'valuex': var2 = var2.successor Para var1 - se ele poderia ser um objeto que implementou uma interface que sabia como lidar. o que você está fazendo dentro do loop, e cada classe implementando sabia o que, especificamente, deve fazer ... Bem, você estaria feito.

Update:

E aqui está um pouco de função sucessor dandy em um caso de teste:

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

Você pode usar um mapa simples:

enum MyEnum { A, B, C };

Map<MyEnum, MyEnum> VALUE_X = new HashMap<MyEnum, MyEnum>() {{
    put(MyEnum.A, MyEnum.B);
    put(MyEnum.B, MyEnum.C);
    ...
}};

// define another kind of ordering
Map<MyEnum, MyEnum> VALUE_Y = new HashMap<MyEnum, MyEnum>() {{
    put(MyEnum.A, MyEnum.D);
    put(MyEnum.B, MyEnum.A);
    ...
}};

Desta forma, a lógica do próximo valor var2 não é codificado no próprio enum, e pode ser dependente do contexto (ou seja, valor de var1):

if ("valueX".equals(var1)) {  // use equals() instead of == for Strings
    var2 = VALUE_X.get(var2);
}
else if ("valueY".equals(var1)) {
    var2 = VALUE_Y.get(var2);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top