The Strategy Pattern (or Policy Pattern) enables a class to select an algorithm's behavior at runtime. It defines a family of algorithms, encapsulates each one, and makes them interchangeable, allowing the algorithm to vary independently from the clients that use it.
In modern Java, creating a full class hierarchy for every strategy is often overkill. Using Functional Interfaces and Lambdas, we can inject behavior directly into the context.
public class CheckoutService {
// Strategy defined as a functional interface
private ToDoubleBiFunction<Double, String> taxStrategy;
public void setTaxStrategy(ToDoubleBiFunction<Double, String> strategy) {
this.taxStrategy = strategy;
}
public double calculateTotal(double amount, String country) {
double tax = taxStrategy.applyAsDouble(amount, country);
return amount + tax;
}
}
// Usage
service.setTaxStrategy((amt, c) -> c.equals("EU") ? amt * 0.21 : amt * 0.05);
For a fixed set of algorithms, an Enum can act as both the registry and the implementation provider. This is highly performant and type-safe.
public enum DiscountPolicy {
RETAIL {
@Override public double apply(double price) { return price; }
},
VIP {
@Override public double apply(double price) { return price * 0.80; }
},
LIQUIDATION {
@Override public double apply(double price) { return price * 0.50; }
};
public abstract double apply(double price);
}
if statement. The pattern is intended for substantial behavioral variations.if/else. Use it when flexibility is required, not as a default for all logic.Context. Prefer passing only the required data (as in the TaxCalculator above) rather than passing the whole Context object to avoid tight coupling.See Also: