javascript / intermediate
Snippet
Dependency Inversion Using Abstract Service Tokens in Angular Providers
By using abstract classes as dependency injection tokens, Angular allows consumers to depend on an abstract interface while dynamically switching the concrete class implementation at provider configuration time. This implements the Dependency Inversion Principle (DIP) in OOP.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { Injectable, Provider } from '@angular/core';export abstract class StorageService {abstract getItem(key: string): string | null;abstract setItem(key: string, value: string): void;}@Injectable()export class LocalStorageService extends StorageService {getItem(key: string): string | null {return localStorage.getItem(key);}setItem(key: string, value: string): void {localStorage.setItem(key, value);}}@Injectable()export class MemoryStorageService extends StorageService {private store = new Map<string, string>();getItem(key: string): string | null {return this.store.get(key) ?? null;}setItem(key: string, value: string): void {this.store.set(key, value);}}export const provideStorage = (useMemory = false): Provider => ({provide: StorageService,useClass: useMemory ? MemoryStorageService : LocalStorageService});
angular
Breakdown
1
export abstract class StorageService {
Defines an abstract base class serving simultaneously as a TypeScript interface and a runtime injection token.
2
export class MemoryStorageService extends StorageService {
Implements an in-memory polymorphism variant of the abstract storage contract.
3
useClass: useMemory ? MemoryStorageService : LocalStorageService
Dynamically selects the concrete class bound to the abstract token depending on runtime or test flags.