Command Palette

Search for a command to run...

PHASE 2Beginner ~8 min· topic 13 of 22Behavioral

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.

0/22 · 0%

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

  1. 01

    Solves: if/else chains over algorithm selection (pricing, payment, matching, parsing).

  2. 02

    Context holds a Strategy reference (injected — constructor or setter).

  3. 03

    Map<String, Strategy> lookup is the modern, OCP-friendly selector.

  4. 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

SplitwiseStrategies.javajava

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

01

Where is the Open/Closed win compared to a switch statement?

Practice

01

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.

Back to phase