Skip to content

Patrones if-else

Los escenarios comunes donde encontramos múltiples if-else son cuando se realizan cálculos o se toma una decisión en base a diferentes parámetros. Veremos cómo optimizar utilizando patrones como Enum, Factory Pattern, Strategy Pattern, y cómo aprovechar las características modernas de Java como el Stream API.

Ejemplo típico de Java con múltiples condicionales if-else:

public class ShippingCostCalculator {
public double calculateShippingCost(String shippingType, double weight) {
if (shippingType.equals("STANDARD")) {
return weight * 5.0;
} else if (shippingType.equals("EXPRESS")) {
return weight * 10.0;
} else if (shippingType.equals("SAME_DAY")) {
return weight * 20.0;
} else if (shippingType.equals("INTERNATIONAL")) {
return weight * 50.0;
} else if (shippingType.equals("OVERNIGHT")) {
return weight * 30.0;
}
return 0;
}
}

Este código realiza cálculos de costos de envío basado en el tipo de envío. Si bien funciona, el uso de if-else para cada tipo de envío genera código difícil de escalar y mantener.


Patrón Enum

Un enfoque efectivo para simplificar el código es utilizar Enum. Veamos cómo podemos optimizar el código anterior:

public enum ShippingType {
STANDARD {
@Override
public double getCost(double weight) {
return weight * 5.0;
}
},
EXPRESS {
@Override
public double getCost(double weight) {
return weight * 10.0;
}
},
SAME_DAY {
@Override
public double getCost(double weight) {
return weight * 20.0;
}
},
INTERNATIONAL {
@Override
public double getCost(double weight) {
return weight * 50.0;
}
},
OVERNIGHT {
@Override
public double getCost(double weight) {
return weight * 30.0;
}
};
public abstract double getCost(double weight);
}
public class ShippingCostCalculator {
public double calculateShippingCost(ShippingType shippingType, double weight) {
return shippingType.getCost(weight);
}
}

Patrón Factory

Si deseas una mayor flexibilidad y separación lógica, el Factory Pattern es una excelente opción. Este patrón te permite crear diferentes estrategias de cálculo dependiendo de los tipos de envío.

Crear la Interfaz ShippingCostStrategy:

public interface ShippingCostStrategy {
double calculate(double weight);
}

Implementar clases específicas para Cada tipo de envío:

public class StandardShipping implements ShippingCostStrategy {
@Override
public double calculate(double weight) {
return weight * 5.0;
}
}
public class ExpressShipping implements ShippingCostStrategy {
@Override
public double calculate(double weight) {
return weight * 10.0;
}
}
// Similarmente para SameDayShipping, InternationalShipping y OvernightShipping...

Crear la Fábrica para Manejar el Enrutamiento:

import java.util.HashMap;
import java.util.Map;
public class ShippingCostFactory {
private static final Map<String, ShippingCostStrategy> strategies = new HashMap<>();
static {
strategies.put("STANDARD", new StandardShipping());
strategies.put("EXPRESS", new ExpressShipping());
strategies.put("SAME_DAY", new SameDayShipping());
strategies.put("INTERNATIONAL", new InternationalShipping());
strategies.put("OVERNIGHT", new OvernightShipping());
}
public static ShippingCostStrategy getStrategy(String shippingType) {
return strategies.getOrDefault(shippingType, () -> 0.0);
}
}

Patrón Strategy

El Strategy Pattern es similar al Factory, pero su enfoque está en cómo se gestiona la lógica interna de cada cálculo.

Interfaz Strategy:

public interface ShippingCostStrategy {
double calculate(double weight);
}

Contexto que Maneja las Estrategias:

public class ShippingCostContext {
private ShippingCostStrategy strategy;
public void setStrategy(ShippingCostStrategy strategy) {
this.strategy = strategy;
}
public double calculateShippingCost(double weight) {
return strategy.calculate(weight);
}
}

Uso del Patrón Strategy:

public class ShippingCostCalculator {
private final ShippingCostContext context = new ShippingCostContext();
public double calculateShippingCost(String shippingType, double weight) {
ShippingCostStrategy strategy = ShippingCostFactory.getStrategy(shippingType);
context.setStrategy(strategy);
return context.calculateShippingCost(weight);
}
}

Stream API y Map

Si prefieres una solución más compacta y moderna, puedes usar el Stream API y Map para manejar las condiciones:

import java.util.HashMap;
import java.util.Map;
public class ShippingCostCalculator {
private static final Map<String, Double> shippingCosts = new HashMap<>();
static {
shippingCosts.put("STANDARD", 5.0);
shippingCosts.put("EXPRESS", 10.0);
shippingCosts.put("SAME_DAY", 20.0);
shippingCosts.put("INTERNATIONAL", 50.0);
shippingCosts.put("OVERNIGHT", 30.0);
}
public double calculateShippingCost(String shippingType, double weight) {
return shippingCosts.getOrDefault(shippingType.toUpperCase(), 0.0) * weight;
}
}