Factory Pattern in TypeScript

Lukas Gamper, uSystems GmbH

Design Pattern Types

  • Creational: deal with object creation
  • Structural: deal with relationships between
    objects (or other entities)
  • Behavioural: deal with communication
    patterns between objects
  • Concurrency: deal with multi-threaded paradigms

Factory Pattern

The factory pattern is one of the creational software design patterns.

This design pattern provides a generic interface to create objects.

It works with a creator that produces products. When using the factory pattern, we are not required to use the new keyword because the instantiation of additional classes are done in the factory implementation.

Selfcontaining Factory

// beerfactory.ts
export class BeerFactory {
    constructor(
        public brand: string, 
        public name: string
    ) {}

    public get label(): void {
        console.log(`${this.name} by ${this.brand}`);
    }
}

export default function createBeer(brand: string, name: string) {
  return new BeerFactory(name, health);
}
// app.ts
import createBeer, { BeerFactory } from './beerfactory';

const waldbier: BeerFactory = createBeer('Waldbeer', 'Pilgrim');
waldbier.label(); // Waldbeer by Pilgrim

Factory

// beerfactory.ts
import Beer from 'beer';
export default class BeerFactory {
    private instances: Beer[] = [];
    public create(brand: string, name: string) {
        const instance: Beer = new Beer(brand, name);
        this.instances.push(instance);
        return instance;
    }
    public get beers(): Beer[] {
        return [...this.instances];
    }
}
// beer.ts
export default class Beer {
    constructor(
        public brand: string, 
        public name: string
    ) {}
    public get label(): void {
        console.log(`${this.name} by ${this.brand}`);
    }
}

Factory

// beerfactory.ts
import Beer from 'beer';
export default class BeerFactory {
    private instances: Beer[] = [];
    public create(brand: string, name: string) { ... }
    public get beers(): Beer[] {
        return [...this.instances];
    }
}
// beer.ts
export default class Beer {
    ...
    public get label(): string {
        console.log(`${this.name} by ${this.brand}`);
    }
}
// app.ts
import Beer from './beer';
import BeerFactory from './beerfactory';

const factory: BeerFactory = new BeerFactory();
const waldbier = createBeer('Waldbeer', 'Pilgrim');
waldbier.label(); // Waldbeer by Pilgrim
factory.beers.forEach(beer => beer.label) // Waldbeer by Pilgrim

Factory 2

// strongbeer.ts
import IBeer from 'ibeer'
export default class StrongBeer extends IBeer {
    constructor(
        public brand: string, 
        public name: string
    ) {}
    public get label(): string {
        console.log(`A strong ${this.name} by ${this.brand}`);
    }
}
// ibeer.ts
export default interface IBeer {
    brand: string;
    name: string;
    readonly label: string;
}
// lightbeer.ts
import IBeer from 'ibeer'
export default class LightBeer extends IBeer {
    constructor(
        public brand: string, 
        public name: string
    ) {}
    public get label(): string {
        console.log(`A light ${this.name} by ${this.brand}`);
    }
}

Factory 2

// beerfactory.ts
import IBeer from 'ibeer';
import LightBeer from 'lightbeer';
import StrongBeer from 'strongbeer';
export class BeerFactory {
    private instances: IBeer[] = [];
    public createStrong(brand: string, name: string) {
        const instance: StrongBeer = new StrongBeer(brand, name);
        this.instances.push(instance);
        return instance;
    }
    public createLight(brand: string, name: string) {
        const instance: LightBeer = new LightBeer(brand, name);
        this.instances.push(instance);
        return instance;
    }
    public get beers(): IBeer[] {
        return [...this.instances];
    }
}
// ibeer.ts
export default interface IBeer {
    brand: string;
    public name;
    readonly label: string;
}

Thanks

Factory Pattern in Typescript

By gamperl

Factory Pattern in Typescript

  • 281