Unravel › Java concepts › Design patterns and architecture
Strategy pattern
The strategy pattern puts interchangeable behaviours behind one interface and lets the caller pick one: a PricingStrategy for regular customers and another for members.
Learn these first
At a glance
Choosing how to get to work: car, bike or train.
- 1Define the interface: interface Discount { double apply(double price); }Each implementation is one algorithm. The class that needs it holds a Discount field and calls it.
- 2Pick the strategy at run time (from configuration, user choice, customer type) and pass it in; swapping it requires no if/else in the calling class
- 3With lambdas: Discount member = p -> p * 0.9;Comparator, Predicate and Function are strategies built into the JDK.
- 4Spring injects a Map<String, Discount> of all beans of a type, a handy way to select a strategy by name
- It removes long if/else or switch ladders and supports the open/closed principle: new behaviour means a new class, not an edit to old code
- Do not overdo it: two cases that never change are fine as an if
- The call goes through an interface method (invokeinterface); the JIT inlines it when only one or two implementations are seen at that call site, so there is usually no real cost
import java.util.function.DoubleUnaryOperator;public class Checkout { interface DiscountStrategy { double apply(double price); } static final DiscountStrategy NONE = p -> p; static final DiscountStrategy MEMBER = p -> p * 0.9; private final DiscountStrategy strategy; Checkout(DiscountStrategy strategy) { this.strategy = strategy; } double total(double price) { return strategy.apply(price); }}Read the full explanation (about 1 min)
The strategy pattern puts interchangeable behaviours behind one interface and lets the caller pick one: a PricingStrategy for regular customers and another for members. In modern Java a lambda or a Comparator is often a strategy.
A mental model
Choosing how to get to work: car, bike or train. The destination (the task) is the same; you swap the way of travelling without changing anything else.
How it works
Define the interface: interface Discount { double apply(double price); }. Each implementation is one algorithm. The class that needs it holds a Discount field and calls it.
Pick the strategy at run time (from configuration, user choice, customer type) and pass it in; swapping it requires no if/else in the calling class.
With lambdas: Discount member = p -> p * 0.9;. Comparator, Predicate and Function are strategies built into the JDK.
Spring injects a Map<String, Discount> of all beans of a type, a handy way to select a strategy by name.
Going deeper
It removes long if/else or switch ladders and supports the open/closed principle: new behaviour means a new class, not an edit to old code.
Do not overdo it: two cases that never change are fine as an if. The pattern pays off when variants multiply or are chosen dynamically.
Keep strategies stateless where possible so they can be shared between threads.
Under the hood
The call goes through an interface method (invokeinterface); the JIT inlines it when only one or two implementations are seen at that call site, so there is usually no real cost.
Common mistakes
- A strategy interface with a single implementation that never varies.
- Strategies that need so much context they depend on the caller's internals.
- Stateful shared strategies.
How Unravel recognises it
When you paste code, Unravel looks for these signs of strategy pattern. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
…Strategy
Part of a learning path
- Design patterns and SOLID · previous: Factory pattern · next: Observer and event listeners
Related concepts
Frequently asked questions
What is Strategy pattern?
The strategy pattern puts interchangeable behaviours behind one interface and lets the caller pick one: a PricingStrategy for regular customers and another for members. In modern Java a lambda or a Comparator is often a strategy.
What are the most common mistakes with Strategy pattern?
A strategy interface with a single implementation that never varies. Strategies that need so much context they depend on the caller's internals. Stateful shared strategies.
How can I see Strategy pattern in real code?
Paste your own Java into Unravel and it will point out where strategy pattern appears, explain how it works at the detail level you choose, and draw the flow of the code around it.