Skip to content

Instantly share code, notes, and snippets.

@doronguttman
Last active July 13, 2022 16:31
Show Gist options
  • Save doronguttman/997f000df7dcf4ab5bdced8efbc7ed07 to your computer and use it in GitHub Desktop.
Save doronguttman/997f000df7dcf4ab5bdced8efbc7ed07 to your computer and use it in GitHub Desktop.
Nest.js Strategy Pattern
import { StrategyModule } from "./strategy.module";
(async () => {
try {
const moduleRef = await Test.createTestingModule({
imports: [StrategyModule]
}).compile();
const factory = moduleRef.get(StrategyFactoryService);
factory.getStrategy("strategy-1").execute();
factory.getStrategy("strategy-2").execute();
} catch (error) {
console.error(error);
}
}
})();
import { Injectable } from "@nestjs/common";
import { StrategyBase } from "./strategy-base";
@Injectable()
export class Strategy1 extends StrategyBase {
public get name(): string { return "strategy-1"; }
public execute(): void {
console.log("Strategy 1");
}
}
import { Injectable } from "@nestjs/common";
import { StrategyBase } from "./strategy-base";
@Injectable()
export class Strategy2 extends StrategyBase {
public get name(): string { return "strategy-2"; }
public execute(): void {
console.log("Strategy 2");
}
}
export abstract class StrategyBase {
public abstract get name(): string;
public abstract execute(): void;
}
import { Injectable } from "@nestjs/common";
import { StrategyBase } from "./strategy-base";
import { Strategy1 } from "./strategy-1.service";
import { Strategy2 } from "./strategy-2.service";
import { ModuleRef } from "@nestjs/core";
const STRATEGIES = [
Strategy1,
Strategy2
] as const;
@Injectable()
export class StrategyFactoryService {
readonly #strategies: Map<string, StrategyBase>;;
constructor(
moduleRef: ModuleRef,
) {
const instances = StrategyFactoryService.strategies.map(strategy => moduleRef.get(strategy));
this.#strategies = new Map(instances.map(strategy => [strategy.name, strategy]));
}
public static get strategies(): typeof STRATEGIES {
return STRATEGIES;
}
public tryGetStrategy(name: string): StrategyBase | undefined {
return this.#strategies.get(name);
}
public getStrategy(name: string): StrategyBase {
const strategy = this.tryGetStrategy(name);
if (!strategy) {
throw new Error(`Strategy ${name} not found`);
}
return strategy;
}
}
import { Module } from "@nestjs/common";
import { Test } from "@nestjs/testing";
import { StrategyFactoryService } from "./strategy-factory.service";
@Module({
providers: [StrategyFactoryService, ...StrategyFactoryService.strategies],
exports: [StrategyFactoryService]
})
export class StrategyModule { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment