Substituir Condicional por Polimorfismo.
Você tem um condicional que executa várias ações dependendo do tipo ou das propriedades de um objeto.
Crie subclasses correspondentes aos ramos do condicional. Nelas, crie um método compartilhado e mova para ele o código do ramo correspondente do condicional. Em seguida, substitua o condicional pela chamada do método relevante. O resultado é que a implementação adequada será obtida por meio de polimorfismo, dependendo da classe do objeto.
##Example
class Bird {
// ...
double getSpeed() {
switch (type) {
case EUROPEAN:
return getBaseSpeed();
case AFRICAN:
return getBaseSpeed() - getLoadFactor() * numberOfCoconuts;
case NORWEGIAN_BLUE:
return (isNailed) ? 0 : getBaseSpeed(voltage);
}
throw new RuntimeException("Should be unreachable");
}
}abstract class Bird {
// ...
abstract double getSpeed();
}
class European extends Bird {
double getSpeed() {
return getBaseSpeed();
}
}
class African extends Bird {
double getSpeed() {
return getBaseSpeed() - getLoadFactor() * numberOfCoconuts;
}
}
class NorwegianBlue extends Bird {
double getSpeed() {
return (isNailed) ? 0 : getBaseSpeed(voltage);
}
}
// Em algum lugar do código cliente
speed = bird.getSpeed();##Why Refactor
Esta técnica de refatoração pode ajudar se seu código contém operadores que executam várias tarefas que variam com base em:
-
Classe do objeto ou interface que ele implementa
-
Valor de um campo do objeto
-
Resultado da chamada de um dos métodos do objeto
Se uma nova propriedade ou tipo de objeto aparecer, você precisará procurar e adicionar código em todos os condicionais semelhantes. Assim, o benefício desta técnica é multiplicado se houver vários condicionais espalhados por todos os métodos de um objeto.
##Benefits
-
Esta técnica adere ao princípio Tell-Don’t-Ask: em vez de perguntar a um objeto sobre seu estado e então executar ações com base nisso, é muito mais fácil simplesmente dizer ao objeto o que ele precisa fazer e deixar que ele mesmo decida como fazê-lo.
-
Remove código duplicado. Você se livra de muitos condicionais quase idênticos.
-
Se você precisar adicionar uma nova variante de execução, basta adicionar uma nova subclasse sem tocar no código existente (Princípio Aberto/Fechado).
##How to Refactor
Preparando-se para Refatorar
Para esta técnica de refatoração, você deve ter uma hierarquia de classes pronta que conterá comportamentos alternativos. Se você não tiver uma hierarquia como essa, crie uma. Outras técnicas ajudarão a tornar isso possível:
-
Substituir Código de Tipo por Subclasses. Serão criadas subclasses para todos os valores de uma determinada propriedade do objeto. Essa abordagem é simples, mas menos flexível, já que você não pode criar subclasses para as outras propriedades do objeto.
-
Substituir Código de Tipo por State/Strategy. Uma classe será dedicada a uma determinada propriedade do objeto, e a partir dela serão criadas subclasses para cada valor da propriedade. A classe atual conterá referências aos objetos desse tipo e delegará a execução a eles.
Os passos a seguir pressupõem que você já criou a hierarquia.
Passos da Refatoração
-
Se o condicional estiver em um método que também executa outras ações, aplique Extrair Método.
-
Para cada subclasse da hierarquia, redefina o método que contém o condicional e copie o código do ramo correspondente do condicional para esse local.
-
Exclua esse ramo do condicional.
-
Repita a substituição até que o condicional fique vazio. Em seguida, exclua o condicional e declare o método como abstrato.