Phase 6 · Design patterns · Topic 6.7

Strategy

Must know

Puts a family of interchangeable algorithms behind one interface, so you can choose one at runtime.

Not started

Step 1 Understand it

The problem it solves. When an algorithm can vary (pricing, sorting, routing), putting every variant in one method with if/else makes it long, hard to test and risky to extend.

New words in this topic (tap one to see what it means)

Watch it happen

AnimationStrategy: swap the algorithm without touching its user
Read the animation as text
  1. Instead of an if/elif on the pricing type inside Ride, each pricing rule is its own class with the same method: price(distance_km).
  2. Ride holds one strategy and just calls it. Normal pricing for 10 km: £14.50.
  3. Rush hour: swap the strategy at runtime — from configuration, a factory or the clock. Same Ride, same call: £26.10.
  4. A new rule is a new class. Ride never changes, and each strategy can be tested on its own.

Picture it

classDiagram
  class Ride {
    -pricing
    +fare(km)
  }
  class PricingStrategy {
    <<interface>>
    +price(km)
  }
  Ride o-- PricingStrategy
  PricingStrategy <|.. NormalPricing
  PricingStrategy <|.. SurgePricing
  PricingStrategy <|.. NightPricing
Ride holds one pricing and can swap it for any other that implements the same .

The idea

Instead of an if/elif on pricing type inside checkout, each pricing rule is its own (or function) with the same method. Checkout holds one strategy and can swap it.

How it works, step by step

  1. Define the interface: price(distance_km).
  2. Write one class per algorithm: NormalPricing, SurgePricing, NightPricing.
  3. The context (Ride) holds one strategy object and calls it.
  4. Choose the strategy at runtime: from configuration, a , or the time of day.

Analogy

Choosing a route in a maps app: fastest, shortest or avoiding tolls. Same journey, different strategy.

Where the analogy breaks

The maps app chooses for you when you tap a button. In code, something still has to decide which strategy to use, often a factory or configuration.

Example

Payment fees, sorting, compression formats, and ride pricing (normal or ).

Must-know points

  • Replaces 'which algorithm?' conditionals with .
  • Strategies can be swapped at runtime.
  • In Python, plain functions can be strategies.
  • Very common in LLD answers: pricing, payment, parking fees.

Common mistakes

  • Strategies that need lots of the context's private data (a sign the interface is wrong).
  • Creating strategy classes for one fixed algorithm.
python
class NormalPricing:
    def price(self, distance_km): return 2 + 1.2 * distance_km

class SurgePricing:
    def __init__(self, multiplier): self.multiplier = multiplier
    def price(self, distance_km): return (2 + 1.2 * distance_km) * self.multiplier

class Ride:
    def __init__(self, pricing): self.pricing = pricing    # a swappable strategy
    def fare(self, km): return round(self.pricing.price(km), 2)

Ride(NormalPricing()).fare(10)        # 14.0
Ride(SurgePricing(1.5)).fare(10)      # 21.0

Step 2 Go further (free, optional)

Optional. The notes above are written to be enough on their own. These free resources give a second explanation and extra practice.

Step 3 Practise

Try each exercise yourself first: on paper, out loud or in code. Then open the answer and compare it with yours.

  1. ExplainSay it in plain words in under a minute, with no notes.

    Explain Strategy with the route-choice picture.

    Show answer

    In a maps app, the journey is the same, from home to the airport, but you choose how the route is worked out: fastest, shortest, or avoiding tolls. The app doesn't care which you pick; it asks the chosen option for a route and follows it. You can switch options without changing anything else.

    Strategy is that idea in code. One job (working out a ride's price) has several interchangeable ways of being done (normal pricing, surge pricing). Each way is its own class (or function) with the same method, price(distance). The Ride holds one strategy and calls it, without knowing which one it has. Swapping the strategy changes the behaviour; adding a new one needs no change to Ride. It replaces an if/elif on "pricing type" in the middle of the business code.

  2. DrawSketch the diagram (or class diagram) from memory.

    Draw Ride with a PricingStrategy interface and two implementations.

    Show answer

    Ride holds one PricingStrategy and only ever calls price(). Each implementation is interchangeable. Night pricing is added as one more box at the bottom, without touching Ride.

    text
    Ride
     - pricing: PricingStrategy  ◆──► «interface» PricingStrategy
     + fare(km)                         + price(distance_km)
                                          △          △           △
                                          ┊          ┊           ┊
                               NormalPricing   SurgePricing   NightPricing
                               2 + 1.2 × km    normal × 1.5   normal + £3
                                                              (added later)
  3. ApplyUse it in a real design question and say exactly where it fits.

    Add a 'night pricing' strategy without changing Ride, and write tests for all three.

    Show answer

    NightPricing is one new class with the same price() method: here a flat £3 on top of the normal fare. Ride is not changed. Each strategy gets a test for a 10 km ride: normal £14.00, surge (× 1.5) £21.00, night £17.00, and one more test checks that strategies can be swapped on the same ride.

    python
    class NormalPricing:
        def price(self, distance_km): return 2 + 1.2 * distance_km
    
    
    class SurgePricing:
        def __init__(self, multiplier): self.multiplier = multiplier
        def price(self, distance_km): return (2 + 1.2 * distance_km) * self.multiplier
    
    
    class NightPricing:                               # new: Ride is not changed
        def price(self, distance_km): return NormalPricing().price(distance_km) + 3
    
    
    class Ride:
        def __init__(self, pricing): self.pricing = pricing
        def fare(self, km): return round(self.pricing.price(km), 2)
    
    
    def test_normal():
        assert Ride(NormalPricing()).fare(10) == 14.0
    
    
    def test_surge():
        assert Ride(SurgePricing(1.5)).fare(10) == 21.0
    
    
    def test_night():
        assert Ride(NightPricing()).fare(10) == 17.0
    
    
    def test_strategy_can_be_swapped():
        ride = Ride(NormalPricing())
        ride.pricing = NightPricing()
        assert ride.fare(10) == 17.0
    
    
    for test in (test_normal, test_surge, test_night, test_strategy_can_be_swapped):
        test()
    print("all 4 tests passed")                       # all 4 tests passed
  4. Trade-offsSay what it costs, when not to use it, and the alternative.

    When is a simple if/else better than Strategy?

    Show answer

    • Two or three options that rarely change, each only a line or two: an if/else is shorter and easier to read than an interface and three classes.
    • The choice is used in one place only, so nothing else would reuse the strategies.
    • The behaviour never needs to be swapped at runtime, configured, or tested separately.
    • It is really data, not behaviour: if the options only differ in numbers (a rate per km), a table of numbers is enough.

    In Python there is also a lighter middle ground: functions are already strategies. Pass a function, or keep a dictionary from name to function, without writing classes.

    Move to Strategy when the options multiply, when each grows its own logic, when other teams add options, or when you want to test each option on its own.

Step 4 Interview-ready, then prove it

Your interview answer

About 20 to 40 seconds, said out loud. Practise it until it sounds like you, not like notes.

Strategy puts each interchangeable algorithm, like normal or surge pricing, behind one interface, so the class using it can switch algorithms at runtime, and new ones are added without editing it.

Follow-up questions

Strategy or State?

Both swap behaviour objects. With Strategy, the caller chooses the algorithm. With State, the object changes its own state as happen.

Tick each check when you can do it without notes

A topic is finished when you pass all four checks, not when you finish a video. Be strict: if you needed your notes, it is not ticked yet.

  • Explain Say it in plain words in under a minute, with no notes.
  • Draw Sketch the diagram (or class diagram) from memory.
  • Apply Use it in a real design question and say exactly where it fits.
  • Trade-offs Say what it costs, when not to use it, and the alternative.

0 of 4 checks ticked.

Saved in this browser. Back it up or move it to another device.