Difficulty: Intermediate
What is the Strategy pattern? How does it replace if-else chains, and how is it different from the State pattern?
The Strategy pattern defines a family of interchangeable algorithms, puts each behind a common interface, and lets the client choose which one to use, even at run time. Imagine using a maps app. The destination is the same, but you can pick driving, walking, or public transit as the routing strategy. The app's screen does not change; only the route calculation does.
Here is the everyday coding problem it solves. You are building a shopping cart with discounts: none, festival half-price, flat 200 rupees off, student discount, and more coming each month. The naive design puts a method checkout with a big if-else on discount type, so every new offer means editing the same method. It violates the Open/Closed Principle, makes the method hard to test, and mixes many responsibilities.
With Strategy, you define a DiscountStrategy interface with one method, apply. Each offer becomes its own small class or, in modern Java, a lambda. The Cart holds a reference to a DiscountStrategy and delegates to it. Adding a new offer means adding a new implementation; Cart never changes. Because the strategy is a field, you can swap it while the program runs, exactly what the example does when the offer changes from none to half-price to flat discount.
The structure has three parts: the Strategy interface, concrete strategies, and the Context that holds and uses a strategy. It is the textbook example of composition over inheritance, since behaviour is plugged in rather than inherited via subclasses like FestivalCart and StudentCart, which would explode combinatorially.
Java's own library uses Strategy heavily: Comparator passed to Collections.sort or list.sort is a strategy for ordering; the RejectedExecutionHandler of a ThreadPoolExecutor is a strategy; Spring Security's PasswordEncoder is a strategy. Since Java 8, a single-method strategy is a functional interface, so lambdas and method references replace tiny classes.
The comparison with State is a classic follow-up. Structurally they look almost identical: a context delegating to an interface. The difference is in intent and who controls the switch. In Strategy, the client picks the algorithm, strategies do not know about each other, and the choice is usually stable for a while. In State, the object changes its own behaviour as its internal state changes, the states know about the transitions to other states, and the client normally does not choose. A vending machine moving from Idle to HasMoney is State; choosing a sort order is Strategy.
Also compare with Template Method: Template Method varies steps of an algorithm through inheritance, while Strategy varies the whole algorithm through composition and can be changed at run time.
When not to use it: if you have only two stable variants that will never change, a simple conditional is fine. Avoid creating a strategy hierarchy for the sake of patterns.
interface DiscountStrategy { double apply(double amount); }
class Cart {
private DiscountStrategy strategy;
Cart(DiscountStrategy strategy) { this.strategy = strategy; }
void setStrategy(DiscountStrategy s) { this.strategy = s; }
double checkout(double amount) { return strategy.apply(amount); }
}
public class StrategyDemo {
public static void main(String[] args) {
Cart cart = new Cart(a -> a); // no discount
System.out.println(cart.checkout(1000));
cart.setStrategy(a -> a * 0.5); // festival half price
System.out.println(cart.checkout(1000));
cart.setStrategy(a -> a - 200); // flat 200 off
System.out.println(cart.checkout(1000));
}
}
Each lambda is a strategy; the Cart is unchanged when a new offer appears.
strategy, design-patterns, behavioral, composition, open-closed