Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each, and makes them interchangeable.
Introduction
The Strategy pattern defines a family of algorithms, encapsulates each, and makes them interchangeable. Elevator scheduling (FCFS vs SCAN), pricing rules, and payment routing are classic LLD examples.
Strategy is polymorphism applied to behavior variation — client holds Strategy interface and delegates without conditionals. Interview extensions often ask for new strategy without changing client code.
Inject strategy via constructor for testability.
Understanding the topic
Key concepts
- Strategy interface declares algorithm method.
- Concrete strategies implement different algorithms.
- Context class delegates to strategy instance.
- Runtime strategy swap possible if requirements allow.
- Eliminates growing switch statements.
- Related to OCP and DIP directly.
flowchart LRSubject -->|notify| ObserverASubject -->|notify| ObserverB
Step-by-step explanation
- Identify varying algorithm (fare, scheduling, compression).
- Extract Strategy interface with compute method.
- Implement one class per algorithm.
- Context stores Strategy field set at construction.
- Client calls context method; context delegates.
- Add strategies by new classes only.
Informative example
Elevator dispatch strategies:
public interface DispatchStrategy {int selectElevator(List<Elevator> elevators, int requestedFloor);}public final class NearestCarStrategy implements DispatchStrategy {@Overridepublic int selectElevator(List<Elevator> elevators, int requestedFloor) {return elevators.stream().min(Comparator.comparingInt(e -> Math.abs(e.currentFloor() - requestedFloor))).orElseThrow().id();}}public final class ElevatorController {private final List<Elevator> elevators;private final DispatchStrategy strategy;public ElevatorController(List<Elevator> elevators, DispatchStrategy strategy) {this.elevators = elevators;this.strategy = strategy;}public void requestFloor(int floor) {int id = strategy.selectElevator(elevators, floor);elevators.stream().filter(e -> e.id() == id).findFirst().orElseThrow().addRequest(floor);}}
Swap NearestCarStrategy for LoadBalancedStrategy in tests — controller unchanged.
Real-world use
Real-world applications
- Pricing, tax, routing, sorting policies.
- Compression or validation rules.
- Game AI difficulty levels.
Best practices
- Keep strategies stateless when possible.
- Name strategies after algorithm (SCAN, FIFO).
- Inject strategy — avoid hard-coded new in methods.
- Unit test each strategy independently.
- Document strategy selection criteria.
Common mistakes
- Strategy with hidden context mutation.
- One strategy class with mode flag (inside switch).
- Context knowing all concrete strategy types.
- Over-strategizing trivial one-line differences.
Advanced interview questions
Q1BeginnerWhat is Strategy pattern?
Q2BeginnerStrategy vs if-else?
Q3IntermediateWhere does strategy get chosen?
Q4IntermediateStrategy vs State pattern?
Q5AdvancedAdd surge pricing to cab booking.
Summary
Strategy encapsulates swappable algorithms. Removes conditional logic from clients. Supports OCP for new algorithms. Inject via constructor in Java LLD. Ideal for pricing, dispatch, and routing.