Imagine a furniture factory that creates these products

  • Chair
  • Coffee Table
  • Sofa

Each of mentioned products could be made different type of materials here we consider two type of materials

  • Modern
  • Old

Our Factory

We have 3 products so we will create an interface for each of them and an interface for our lovely factory that creates these products.

Different Types

Our factory can create products in different types.
For example in chair interface, material property could be wood or aluminum or coffee table may have 2 or 4 legs.
How we are going to manage these types?

We will create a sub factory makes special type of our products. as mentioned at first we will create two types, material and old.

Here is our interfaces

Interfaces

interface Chair {
    legs: number,
    arms: number,
    material: string
}

interface CoffeeTable {
    legs: number,
    material: string,
    hasGlass: boolean
}

interface Sofa {
    legs: number,
    arms: number,
    material: string
}

interface FurnitureFactory {
    createChair(): Chair,
    createCoffeeTable(): CoffeeTable,
    createSofa(): Sofa
}

Modern Furniture Factory

In modern factory we used aluminium as material for products


class ModernFurnitureFactory implements FurnitureFactory{
    createChair(): Chair {
        return this.createModernChair();
    }

    createCoffeeTable(): CoffeeTable {
        return this.createModernCoffeTable()
    }

    createSofa(): Sofa {
        return this.createMoernSofa()
    }

    private createModernChair(): Chair {
        let chair: Chair = {} as Chair;
        chair.arms = 0;
        chair.legs = 1;
        chair.material = 'Aluminium';
        return chair
    }

    private createModernCoffeTable(): CoffeeTable {
        let coffeeTable: CoffeeTable = {} as CoffeeTable;
        coffeeTable.hasGlass = true;
        coffeeTable.legs = 2;
        coffeeTable.material = 'Aluminium';
        return coffeeTable
    }

    private createMoernSofa(): Sofa {
        let sofa: Sofa = {} as Sofa;
        sofa.arms = 0;
        sofa.legs = 1;
        return sofa
    }

}

Old Furniture Factory


class OldFurnitureFactory implements FurnitureFactory{
    createChair(): Chair {
        return this.createOldChair();
    }

    createCoffeeTable(): CoffeeTable {
        return this.createOldCoffeTable();
    }

    createSofa(): Sofa {
        return this.createOldSofa();
    }

    private createOldChair(): Chair {
        let chair: Chair = {} as Chair;
        chair.arms = 2;
        chair.legs = 2;
        chair.material = 'Wood';
        return chair
    }

    private createOldCoffeTable(): CoffeeTable {
        let coffeeTable: CoffeeTable = {} as CoffeeTable;
        coffeeTable.hasGlass = false;
        coffeeTable.legs = 4;
        coffeeTable.material = 'Wood';
        return coffeeTable
    }

    private createOldSofa(): Sofa {
        let sofa: Sofa = {} as Sofa;
        sofa.arms = 2;
        sofa.legs = 2;
        return sofa
    }

}

Benefits

With Abstract Factory design pattern, without modifying your previous code, you can add new type of factories (second principle of SOLID, open to extend, closed to modify).
For example you can create Classic Furniture Factory that uses another thing for material and is not using glass for coffee table.

Codes in Github

https://github.com/mrfarhadir/design-patterns/blob/master/AbstractFactory/furniture-factory/

Leave your thoughts 🙂