Mariusz Rajczakowski
Software Engineer
4 min read | 4 months ago

Strategy Design Pattern

Strategy Design Pattern

Strategy is a behavioral design pattern which:

  • defines a family of alorithms
  • encapsulate each one
  • make them interchangable

Strategy allows algorithms vary independently from the clients using it.

What problems can strategy solve?

Class that implements algorithm directly is inflexible as changing algorithm later independently from the class (without changing the class) might be impossible.

It also stops the class from being reusable when another algorithm should be used.

What solution does the Strategy design pattern describe?

It defines a separate object that encapsulate algorithm.

It defines an interface (Strategy) for performing an algorithm, and concrete classes that implement algorithm in different ways.

Class can be configured with particular strategy object, but can also be exchanged in run-time upon certain condition.

UML diagram for strategy

strategy uml diagram

Examples

Game characters:


interface WeaponStrategy {
  readonly attack: () => void;
}

class SwordStrategy implements WeaponStrategy {
  attack(){
     //console.log('using sword...');
  }
}

class WandStrategy implements WeaponStrategy {
  attack(){
     //console.log('using wand...');
  }
}

class Character { 
  public setWeapon(weapon: WeaponStrategy){
     this.weapon = weapon;
  }

  attack(){
    //context using strategy
    this.weapon.attack();
  }
}

class Knight extends Character {
  constructor(){
    //default strategy
    this.weapon = new SwordStrategy();
  } 
}

class Sorcerer extends Character {
  constructor(){
    //default strategy
    this.weapon = new WandStrategy();
  } 
}

const sorcerer = new Sorcerer();
sorcerer.attack(); //prints 'using wand...'
sorcerer.setWeapon(new SwordStrategy());
sorcerer.attack(); //prints using sword...

Bike brakes


interface BrakesStrategy {
  readonly break: () => void;
}

class VBrakesStrategy implements BrakesStrategy {
  break(){
     //console.log('using v-brakes...');
  }
}

class HydraulicDiscBrakesStrategy implements BrakesStrategy {
  break(){
     //console.log('using hydaulic disc brakes...');
  }
}

interface Brakes {
  readonly brake: () => void;
}

class MountainBike implements Brakes { 
  public changeBrakes(brakes: BrakesStrategy){
     this.brakes = brakes;
  }

 constructor(){
    //default strategy
    this.brakes = new VBrakesStrategy();
  } 

  brake(){
    //context using strategy
    this.brakes.brake();
  }
}

const myBike = new MountainBike();
//some obstacle on the road...
myBike.break(); //prints 'using v-brakes...'
//going on the trip in the mountains where it can rains...
myBike.changeBrakes(new HydraulicDiscBrakesStrategy());
myBike.break(); // prints using hydaulic disc brakes...

Discounts:


type DiscountStrategy = (originalPrice: number) => number; 

const SummerSaleStrategy:DiscountStrategy = (originalPrice: ) => {
  return originalPrice * 0.6;
}

const NormalDiscountStrategy:DiscountStrategy = (originalPrice) => {
  return originalPrice * 0.9;
}

const calculateProductPrice = (productPrice: number, applyDiscount: DiscountStrategy) => 
{
  return applyDiscount(productPrice);
}

const carPrice = 25000;
const month: number = 7; 
const discount = (month === 7 || month === 8) ? SummerSaleStrategy : NormalDiscountStrategy;
const carPriceAfterDiscount: number = calculateProductPrice(carPrice, discount);
console.log(carPriceAfterDiscount); // prints 15000

Sorting:



type SortingStrategy = (x: any, y: any) => number;

const ascending: SortingStrategy = (x, y) => x - y;
const descending: SortingStrategy = (x, y) => y - x;

const data: number[] = [15, 1, 3, 51];
const ascendingNumbers: number[]  = data.sort(ascending); // [1, 3, 15, 51]
const descendingNumbers: number[] = data.sort(descending); // [51, 15, 3, 1]

Takeaway notes

Strategy design pattern can be used when the part of class can change frequently, or subclasses just slightly differ in behavior so can implement same interface and become interchangable (avoiding duplication and making code loosely coupled).

References
  1. https://en.wikipedia.org/wiki/Strategy_pattern
  2. https://stackoverflow.com/questions/370258/real-world-example-of-the-strategy-pattern/35180265#35180265
  3. http://robdodson.me/javascript-design-patterns-strategy/

Share:



Warning! This site uses cookies
By continuing to browse the site, you are agreeing to our use of cookies. Read our privacy policy