A Live Developer Journal

The Strategy Pattern - Design Pattern Series

A strategy is an action you can take to achieve a specific outcome. Depending on your circumstances, you might want to try out one action over another.

If you happen to be a cat named Leo (DeCatprio) and your outcome is to get attention, the strategies you could use are:

Which strategy you use at any given point can be decided by you, or something else can decide for you. For example, you might decide to get attention when you realise that you're hungry, or your hooman might ask you to get attention so they can make you a star on YouTube. What's important is that you've been trained to respond to the message "get attention".

When you hear the message "get attention", you immediately delegate that behavior to the only strategy you know about (the one you were given by yourself or someone else, or default behaviour if none was given).

You ask whatever strategy you know about to go and "get attention" on your behalf. The strategy then goes and implements that behaviour and passes the result back to you, which you then pass back to yourself or the person that asked you to get attention in the first place.

The person (or stomach) that asked you to get attention has no idea how you got it, and they don't care because they have the result of that behaviour which is all they cared about.

You the kitty (not your stomach) also have no idea how you got attention, because you delegated it. You're also pretty happy about this because anytime a new strategy for getting attention is discovered, you'll be able to use it straight away without ever having to remember how to do all of them at once.


// Strategy Interface - Says: "All strategies will have a seek method that returns a string value"
interface Attention {
  seek(): string
}

// Concrete Strategy - The implementation of a specific strategy. Make one for each strategy
class MeowLoudlyAndRepeatedly implements Attention {
  seek(): string { return "MEOW! MEOW! MEOW! MEOW!" }
}

class KnockThingsOffTheTable implements Attention {
  seek(): string { return "*Knocks one item off the table while looking straight at you*" }
}

// Context Object - Has a concrete strategy (or default behaviour) that can be switched out and used
class Kitty {
  attention: Attention = new MeowLoudlyAndRepeatedly

  getAttentionBy(strategy: Attention): void { this.attention = strategy }
  getAttention(): string { return this.attention.seek() }
}

// Using the above in practice - So easy to switch out strategies
const leoDecatprio = new Kitty
leoDecatprio.getAttention()
leoDecatprio.getAttentionBy(new KnockThingsOffTheTable)
leoDecatprio.getAttention()

Sometimes, the strategy needs data from the context object (or vise versa). There are two ways to do this mentioned in the design pattern book.

  1. The context object (kitty) passes it's own data (hunger status) to the strategy method (getAttention()).
  2. The context object passes itself (this) to the strategy method (getAttention()).

Which you choose depend on whether different strategies care about different information (pass the whole context), or whether they all only care about one or two things (pass the data).

Clients and default behaviour

Extra Tip

Name methods from the point of view of the caller.