SwadhyAI Notes

All Low-Level Design notes

Behavioral · Gang of Four

Strategy

Strategy is a behavioral pattern that makes an algorithm replaceable. The context object holds a strategy interface and asks it to decide — it does not switch on enums for every rule.

Example: nearest spot, random spot, or EV-only spot; hourly fee, airport fee, or event-day fee. If those rules live as switches inside ParkingLot, the next rule edits the lot. If they are strategies, the lot stays simple. Name the algorithm the interviewer will change before you write the interface.

Interchangeable cards

Strategy is an interface plus implementations the holds. Context stays. Implementations swap. A policy object is the same idea with a domain name.

allocation

Nearest

First free spot that fits.

allocation

Random

Pick among fitting spots.

allocation

EV-only

Ignore petrol spots.

pricing

Hourly

Minutes × rate.

pricing

Airport

Bands + overnight.

pricing

Event-day

Flat surcharge.

Strategy vs State

Picked from outside, or appointed from inside?

State also swaps an object the context holds. Do not mix the names. Strategy is “how do I do this job?” — you choose nearest versus random, and the strategy does not appoint its successor. State is “what am I right now?” — Idle becomes HasCoin because something happened. Pricing and allocation are Strategy. Vending and ATM sessions are State.

LensStrategyState
Who picks the next object?You, a factory, a config flagThe current state, after an event
Why swap?A different algorithm for the same jobThe object’s life changed
Interview pictureParking fees, allocation, win rulesVending, ATM, elevator
Stays until…You replace itA transition fires

Java: allocation as a strategy

Tests pass a . A factory may do the from vehicle type or lot kind. See parking lot.

java
interface SpotAllocationStrategy {
  Optional<ParkingSpot> choose(List<ParkingSpot> free, Vehicle vehicle);
}

class NearestSpotStrategy implements SpotAllocationStrategy {
  public Optional<ParkingSpot> choose(List<ParkingSpot> free, Vehicle vehicle) {
    return free.stream().filter(s -> s.fits(vehicle)).findFirst();
  }
}

interface PricingStrategy {
  Money fee(Ticket ticket, Instant exit);
}

class ParkingLot {
  private final SpotAllocationStrategy allocation;
  private final PricingStrategy pricing;

  ParkingLot(SpotAllocationStrategy allocation, PricingStrategy pricing) {
    this.allocation = allocation;
    this.pricing = pricing;
  }

  Optional<Ticket> park(Vehicle v) {
    return allocation.choose(freeSpots(), v).map(spot -> occupy(spot, v));
  }
}

Protected Variations first

If the formula will never change, a method is enough. See Protected Variations. Strategy second. A is Strategy with a domain name.

Template Method is the inheritance twin

If the whole policy changes, inject a strategy. If the steps stay in order and two of them change, a template is honest. Interviewers often prefer Strategy because you can test the context with a fake.

Starting with the pattern name

“I will use Strategy” is not a design. First say what varies: allocation, pricing, win rules. Then the interface is obvious. Otherwise you invent strategies for things that never change.

A strategy that is a hidden switch

One PricingStrategy implementation with if (type == AIRPORT) inside is the old switch with an interface hat. Each policy should be a type. The switch, if any, lives in a factory that picks the type once.

Name the axis before the interface

“Allocation will change in the follow-up” is a design. “I will use Strategy” is a name. Write SpotAllocationStrategy.choose after you can say the sentence. Two axes (allocation and pricing) are two interfaces, not one MegaStrategy.

  1. 1What varies? Allocation vs pricing vs win rules — pick one sentence.
  2. 2Who stays boring? ParkingLot, Game, Checkout.
  3. 3Who picks the implementation? Constructor, factory, or config — once.
  4. 4How do tests fake it? AlwaysFirstSpot, FixedFee — no subclass of the lot.

Java: factory picks, lot stays simple

The switch lives once. Airport vs hourly are types. ParkingLot never sees Kind.

java
class PricingFactory {
  static PricingStrategy of(LotKind kind) {
    return switch (kind) {
      case AIRPORT -> new AirportPricing();
      case MALL -> new HourlyPricing();
      case EVENT -> new EventDayPricing();
    };
  }
}

How to explain this in an interview

“Allocation will change in the follow-up, so ParkingLot holds SpotAllocationStrategy.” Name the axis first. The interface is then obvious. Idle becoming HasCoin is still State, not a third strategy.

Nearby in LLD