Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strategy Pattern with Angular and Typescript

I would like to implement Strategy pattern in Angular/Typescript and use a service in component; service takes a strategy interface as constructor parameter. Also, constraint is that service is dependent on some other injected service at angular level.

I'm digging through the docs but unable to find a way to do it. I would like not to end up in over-engineered code, searching for simple solution to have a Strategy pattern implemented.

Please see below in mocked-up code:

export interface IStrategy {
    calculate(a,b): number;
}

export class MinusStrategy implements IStrategy {
    calculate(a,b): number {
        return a - b;
    }
}

export class PlusStrategy implements IStrategy {
    calculate(a,b): number {
        return a + b;
    }
}

@Injectable() 
export class CalculatorService {
    // I understand it is not possible to have DI of the Interface here for calcStrategy 
    constructor(private http: HttpClient; private calcStrategy: IStrategy);
    
    getByCalc() {
        this.http.get('someurl?calc=' + calcStrategy.calculate(1,1));
    }
}

@Component(// skipped config here...)
export class MyComponent implements OnInit {
    // How to inject appropriate concrete strategy (and either autowire or provide httpClient?)
    constructor(private service: new CalculatorService(httpClient, new MinusStrategy()));
    
    useInComponent() {
        this.service.getByCalc();
    }
}

like image 288
NenadP Avatar asked Jan 25 '23 22:01

NenadP


1 Answers

My two cents - You cannot rely on DI to provide concrete instance in such case. DI has no way to know which type of instance is needed in each context.

I'd suggest using factory pattern here. For example -

@Injectable()
export class StrategyFactory {
  createStrategy<T extends IStrategy>(c: new () => T): T {
    return new c();
  }
} 

//then you can inject StrategyFactory in your service class, use it like -
factory.createStrategy(MinusStrategy).calculate(2, 1); 
like image 102
ch_g Avatar answered Jan 28 '23 15:01

ch_g