Skip to main content

Strategy

What is?

  • With this pattern we define families of algorithms and make them interchangeable.
  • Code closed to modification and open to expansion

What this pattern solve?

  • If we need to add a method in a class, without this pattern we need to write in the class, making a big code with possibility to has merge conflits.

Steps

  • Identify an algorithm that has frequent changes
  • Declare the strategy common to all variants
  • All variants need to implement that interface method in common

When to use

  • When we want to use variations of an algorithm and be able to switch one to another during runtime.
  • When we have similar classes that differ the way they execute the behavior.
  • When we want to have an isolate business logic
  • When the class has a lot of conditional statement to change the behavior of the same algorithm

Example (Typescript)

interface AnimalStrategy {
saySomething(): string;
}

class Animal {
// Keep a reference to the AnimalStrategy, but don't know the concrete class of the AnimalStrategy
private strategy: AnimalStrategy;

// Define strategy in constructor
constructor(strategy: AnimalStrategy) {
this.strategy = strategy;
}

// Let to change the strategy in runtime
public setStrategy(strategy: AnimalStrategy) {
this.strategy = strategy;
}

// The Animal class use the strategy to implement the method
public giveAHello(): string {
return this.strategy.saySomething();
}
}

// Classes implementing the AnimalStrategy to define the behavior that the class will use
class Dog implements AnimalStrategy {
public saySomething(): string {
return "Au au";
}
}

class Cat implements AnimalStrategy {
public saySomething(): string {
return "Meow";
}
}

// Define a strategy and keep it in runtime
const context = new Animal(new Dog());
console.log('Animal Strategy is a Dog: ', context.giveAHello());

context.setStrategy(new Cat());
console.log('Animal Strategy is a Cat: ', context.giveAHello());