Behavioral 1 — Strategy
In one line
Encapsulate a family of algorithms behind one interface and swap them at runtime — the single most used pattern in LLD interviews.
Think of it like this
Google Maps route options. Car, bike, walk or bus: same start and end, different way of getting there. You pick the strategy, and the app uses it.
Key ideas
- 01
Solves: if/else chains over algorithm selection (pricing, payment, matching, parsing).
- 02
Context holds a Strategy reference (injected — constructor or setter).
- 03
Map<String, Strategy> lookup is the modern, OCP-friendly selector.
- 04
Interview automatic: any time you hear 'multiple ways to X' think Strategy.
Java / Spring map
- →
Comparator is a strategy; Spring injects one strategy per @Qualifier.
Code & diagrams
Expense splitting — the Splitwise problem in miniature. Money is kept in paise (long), never double.
// Amounts are in paise: ₹100.00 = 10000. No rounding surprises.
public interface SplitStrategy {
Map<String, Long> split(long amount, List<String> users, Map<String, Long> input);
}
// EQUAL: ₹100 among 3 → 3334 + 3333 + 3333 (the leftover paisa goes to the first person)
public class EqualSplit implements SplitStrategy {
public Map<String, Long> split(long amount, List<String> users, Map<String, Long> input) {
long each = amount / users.size();
long leftover = amount % users.size();
Map<String, Long> out = new LinkedHashMap<>();
for (int i = 0; i < users.size(); i++) {
out.put(users.get(i), each + (i < leftover ? 1 : 0));
}
return out;
}
}
// PERCENT: input holds percentages (must add up to 100)
public class PercentSplit implements SplitStrategy {
public Map<String, Long> split(long amount, List<String> users, Map<String, Long> pct) {
if (pct.values().stream().mapToLong(Long::longValue).sum() != 100)
throw new IllegalArgumentException("percentages must add up to 100");
Map<String, Long> out = new LinkedHashMap<>();
long given = 0;
for (int i = 0; i < users.size(); i++) {
String u = users.get(i);
long share = (i == users.size() - 1)
? amount - given // last person absorbs rounding
: amount * pct.get(u) / 100;
out.put(u, share);
given += share;
}
return out;
}
}
// EXACT: input holds exact amounts (must add up to the total)
public class ExactSplit implements SplitStrategy {
public Map<String, Long> split(long amount, List<String> users, Map<String, Long> exact) {
if (exact.values().stream().mapToLong(Long::longValue).sum() != amount)
throw new IllegalArgumentException("exact amounts must add up to the total");
return new LinkedHashMap<>(exact);
}
}
// Picking a strategy: add a new one by adding a map entry, not by editing a switch.
public class SplitStrategyRegistry {
private final Map<String, SplitStrategy> map = Map.of(
"equal", new EqualSplit(),
"percent", new PercentSplit(),
"exact", new ExactSplit());
public SplitStrategy by(String type) {
SplitStrategy s = map.get(type);
if (s == null) throw new IllegalArgumentException("unknown split: " + type);
return s;
}
}Explain without notes
Where is the Open/Closed win compared to a switch statement?
Practice
Add a 'ShareSplit' (e.g. 2 shares : 1 share : 1 share) with validation, register it, and note which files did NOT change.
Trade-offs
- ↔
Strategy classes multiply; the registry map adds indirection for simple cases.
Completion checklist
I can spot 'many ways to do X' in a problem and turn it into a Strategy.
My split code never loses or invents a paisa: the parts always add up to the total.