Strategy Design Pattern - DeanHristov/ts-design-patterns-cheat-sheet GitHub Wiki

The Strategy pattern is a behavioral design pattern that gives us the ability to select an algorithm at runtime. Instead of implementing a single algorithm directly (in the code), code receives run-time instructions as to which in a family of algorithms to use. A simple UML diagram can be seen here

A Great fit when:

  1. Algorithms can be selected on the fly, using composition

Example:

Public contracts
export interface IPaymentService {
  pay(amount: number): number;

  isValid(): boolean;
}
Auxiliary classes

A class which represents credit card

class Card {
  cardNumber: string;
  cardHolder: string;
  cvv: number;
  balance: number;

  constructor(
    cardNumber: string,
    cardHolder: string,
    cvv: number,
    balance: number,
  ) {
    this.cardHolder = cardHolder;
    this.cardNumber = cardNumber;
    this.cvv = cvv;
    this.balance = balance;
  }
}

A class which represents PayPal user

class PayPalUser {
  username: string;
  password: string;
  balance: number;

  constructor(username: string, password: string, balance: number) {
    this.username = username;
    this.password = password;
    this.balance = balance;
  }
}
Simple implementation

The Context class. It is not familiar what kind of strategy is used

class PaymentService {
  private strategy: IPaymentService;

  constructor(strategy: IPaymentService) {
    this.strategy = strategy;
  }

  setStrategy(strategy: IPaymentService) {
    this.strategy = strategy;
  }

  processOrder(amount: number) {
    if (this.strategy.isValid()) {
      this.strategy.pay(amount);
      return true;
    }

    return false;
  }
}

The Concrete strategy 1

CreditCardPayment implements IPaymentService {
  private readonly owner: Card;

  constructor(owner: Card) {
    this.owner = owner;
  }

  isValid(): boolean {
    // TODO Do some code
    return true;
  }

  pay(amount: number): number {
    return this.owner.balance - amount;
  }
}

The Concrete strategy 2

class PayPalPayment implements IPaymentService {
  private readonly user: PayPalUser;

  constructor(user: PayPalUser) {
    this.user = user;
  }

  pay(amount: number): number {
    return this.user.balance - amount;
  }

  isValid(): boolean {
    // TODO Do some code
    return true;
  }
}
Code in action
// Processing the order via creditCard
const creditCard: Card = new Card('374245455400126', 'John', 123, 1000);
const strategy: PaymentService = new PaymentService(
  new CreditCardPayment(creditCard),
);
strategy.processOrder(10);

// Processing the order via PayPal
const payPalUser: PayPalUser = new PayPalUser('John', '1234', 1000);

strategy.setStrategy(new PayPalPayment(payPalUser));
strategy.processOrder(20);

More info can be found on the wiki page.