DEV Community

Reza Nazari
Reza Nazari

Posted on

Strategy Pattern in Angular with Injector

Strategy Pattern

Strategy is a behavioral design pattern that lets you define a family of algorithms, put each of them into a separate class, and make their objects interchangeable.

The Strategy pattern suggests that you take a class that does something specific in a lot of different ways and extract all of these algorithms into separate classes called strategies.

The original class, called context, must have a field for storing a reference to one of the strategies. The context delegates the work to a linked strategy object instead of executing it on its own.

Injector

Injectors are data structures that store instructions detailing where and how services form. They act as intermediaries within the Angular DI system.
Module, directive, and component classes contain metadata specific to injectors. A new injector instance accompanies every one of these classes.In this way, the application tree mirrors its hierarchy of injectors.

Dive into code
Imagine that you have to get to the airport. You can catch a bus, order a cab, or get on your bicycle. These are your transportation strategies. You can pick one of the strategies depending on factors such as budget or time constraints.

First we create an abstract class for our transport includes an abstract method called "do_action".

export abstract class TransportStrategy {
  abstract do_action(cost: number): string;

  constructor() {}
}
Enter fullscreen mode Exit fullscreen mode

Then we create a class for each strategy which extends from our strategy abstract class. we have 3 strategies here. Car, bicycle and bus.

import { Injectable } from '@angular/core';

@Injectable()
export class Car extends TransportStrategy {
  do_action(cost: number): string {
    return 'User take a car to go destination, it cost equal ' + cost;
  }
}

@Injectable()
export class Bus extends TransportStrategy {
  do_action(cost: number): string {
    return 'User take a bus to go destination, it cost equal ' + cost;
  }
}

@Injectable()
export class Bicycle extends TransportStrategy {
  do_action(cost: number): string {
    return 'User take a bicycle to go destination, it cost equal ' + cost;
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we need to gather our strategy classes in a place, to control them. so we will get help from typescript Enum and Map.
for better understanding:

Map

The Map object holds key-value pairs and remembers the original insertion order of the keys. Any value (both objects and primitive values) may be used as either a key or a value.

export enum VEHICLES {
  BUS = 'Bus',
  CAR = 'Car',
  BICYCLE = 'Bicycle',
}

export const TransportStaretgyController = new Map<VEHICLES, any>([
  [VEHICLES.BUS, Bus],
  [VEHICLES.CAR, Car],
  [VEHICLES.BICYCLE, Bicycle],
]);

Enter fullscreen mode Exit fullscreen mode

Our strategy classes and their controller are ready. now we should inject them in the component. first inject Injector to component's constructor. also we need a filed which is typeof TransportStrategy class. see below code to find how it will works:

import { Component, Injector, OnInit } from '@angular/core';
import {
  TransportStaretgyController,
  TransportStrategy,
  VEHICLES,
} from '../@service/transport-strategy';

interface Transport {
  vehicle: VEHICLES;
  cost: number;
}

@Component({
  selector: 'app-transportation',
  templateUrl: './transportation.component.html',
  styleUrls: ['./transportation.component.css'],
})
export class TransportationComponent implements OnInit {
  private _transport: TransportStrategy;

  constructor(private injector: Injector) {}

  ngOnInit() {}

  in_choosing_a_strategy(clientStrategy: Transport): void {
    this._transport = this.injector.get<TransportStrategy>(
      TransportStaretgyController.get(clientStrategy.vehicle)
    );

    this._transport.do_action(clientStrategy.cost);
  }
}
Enter fullscreen mode Exit fullscreen mode

In this case, i used dropdown in html file to select strategy. on select a strategy result will be apear on page.
you will find complete code in this repository:
Repo

Resources:
Angular
refactoring.guru

Discussion (0)