📓
Design Patterns & Principles
  • Recipes: Design Patterns And Principles
  • Design Patterns
    • Singleton Pattern
    • Module Pattern
    • Observer Pattern
    • Decorator Pattern
    • Factory Method Pattern
    • Builder Pattern
    • Adapter Pattern
    • Bridge Pattern
    • Composite Pattern
    • Facade Pattern
    • Flyweight Pattern
    • Proxy Pattern
    • Chain of Responsibility
    • Command Pattern
    • Iterator Pattern
    • Mediator Pattern
    • Memento Pattern
    • Visitor Pattern
    • Strategy Pattern
    • State Pattern
    • Template Method Pattern
    • Prototype Pattern
  • Software Principles
    • SOLID Principle
    • DRY Principle
    • Software Architecture Fundamentals
      • Architecture Style
        • Service-Oriented Architecture (SOA)
Powered by GitBook
On this page
  • Simple Factory
  • Factory Method
  • Abstract Factory
  • Resources

Was this helpful?

  1. Design Patterns

Factory Method Pattern

It provides a way to delegate the instantiation logic to child classes.

PreviousDecorator PatternNextBuilder Pattern

Last updated 4 years ago

Was this helpful?

Simple Factory

Real world example

Consider, you are building a house and you need doors. It would be a mess if every time you need a door, you put on your carpenter clothes and start making a door in your house. Instead you get it made from a factory.

In plain words

Simple factory simply generates an instance for client without exposing any instantiation logic to the client

Wikipedia says

In object-oriented programming (OOP), a factory is an object for creating other objects – formally a factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be "new".

Programmatic Example

First of all we have a door interface and the implementation

/*
Door

getWidth()
getHeight()

*/

class WoodenDoor {
  constructor(width, height){
    this.width = width
    this.height = height
  }

  getWidth(){
    return this.width
  }

  getHeight(){
    return this.height
  }
}

Then we have our door factory that makes the door and returns it

const DoorFactory = {
  makeDoor : (width, height) => new WoodenDoor(width, height)
}

And then it can be used as

const door = DoorFactory.makeDoor(100, 200)
console.log('Width:', door.getWidth())
console.log('Height:', door.getHeight())

When to Use?

When creating an object is not just a few assignments and involves some logic, it makes sense to put it in a dedicated factory instead of repeating the same code everywhere.

Real world example

Consider the case of a hiring manager. It is impossible for one person to interview for each of the positions. Based on the job opening, she has to decide and delegate the interview steps to different people.

In plain words

It provides a way to delegate the instantiation logic to child classes.

Wikipedia says

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

Programmatic Example

Taking our hiring manager example above. First of all we have an interviewer interface and some implementations for it

/*
Interviewer interface

askQuestions()
*/

class Developer {
  askQuestions() {
    console.log('Asking about design patterns!')
  }
}

class CommunityExecutive {
  askQuestions() {
    console.log('Asking about community building')
  }
}

Now let us create our HiringManager

class HiringManager {
        
    takeInterview() {
        const interviewer = this.makeInterviewer()
        interviewer.askQuestions()
    }
}

Now any child can extend it and provide the required interviewer

class DevelopmentManager extends HiringManager {
    makeInterviewer() {
        return new Developer()
    }
}

class MarketingManager extends HiringManager {
    makeInterviewer() {
        return new CommunityExecutive()
    }
}

and then it can be used as

const devManager = new DevelopmentManager()
devManager.takeInterview() // Output: Asking about design patterns

const marketingManager = new MarketingManager()
marketingManager.takeInterview() // Output: Asking about community buildng.

When to use?

Useful when there is some generic processing in a class but the required sub-class is dynamically decided at runtime. Or putting it in other words, when the client doesn't know what exact sub-class it might need.

Real world example

Extending our door example from Simple Factory. Based on your needs you might get a wooden door from a wooden door shop, iron door from an iron shop or a PVC door from the relevant shop. Plus you might need a guy with different kind of specialities to fit the door, for example a carpenter for wooden door, welder for iron door etc. As you can see there is a dependency between the doors now, wooden door needs carpenter, iron door needs a welder etc.

In plain words

A factory of factories a factory that groups the individual but related/dependent factories together without specifying their concrete classes.

Wikipedia says

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes

Programmatic Example

Translating the door example above. First of all we have our Door interface and some implementation for it

/*
Door interface :

getDescription()
*/

class WoodenDoor {
    getDescription() {
        console.log('I am a wooden door')
    }
}

class IronDoor {
    getDescription() {
        console.log('I am an iron door')
    }
}

Then we have some fitting experts for each door type

/*
DoorFittingExpert interface :

getDescription()
*/

class Welder {
    getDescription() {
        console.log('I can only fit iron doors')
    }
}

class Carpenter {
    getDescription() {
        console.log('I can only fit wooden doors')
    }
}

Now we have our abstract factory that would let us make family of related objects i.e. wooden door factory would create a wooden door and wooden door fitting expert and iron door factory would create an iron door and iron door fitting expert

/*
DoorFactory interface :

makeDoor()
makeFittingExpert()
*/

// Wooden factory to return carpenter and wooden door
class WoodenDoorFactory {
    makeDoor(){
        return new WoodenDoor()
    }

    makeFittingExpert() {
        return new Carpenter()
    }
}

// Iron door factory to get iron door and the relevant fitting expert
class IronDoorFactory {
    makeDoor(){
        return new IronDoor()
    }

    makeFittingExpert() {
        return new Welder()
    }
}

And then it can be used as

woodenFactory = new WoodenDoorFactory()

door = woodenFactory.makeDoor()
expert = woodenFactory.makeFittingExpert()

door.getDescription()  // Output: I am a wooden door
expert.getDescription() // Output: I can only fit wooden doors

// Same for Iron Factory
ironFactory = new IronDoorFactory()

door = ironFactory.makeDoor()
expert = ironFactory.makeFittingExpert()

door.getDescription()  // Output: I am an iron door
expert.getDescription() // Output: I can only fit iron doors

As you can see the wooden door factory has encapsulated the carpenter and the wooden door also iron door factory has encapsulated the iron door and welder. And thus it had helped us make sure that for each of the created door, we do not get a wrong fitting expert.

When to use?

When there are interrelated dependencies with not-that-simple creation logic involved

Resources

Factory Method

Abstract Factory

house
hammer
factory
GitHub - sohamkamani/javascript-design-patterns-for-humans: An ultra-simplified explanation of design patterns implemented in javascriptGitHub
Logo
JavaScript design patterns #2. Factories and their implementation in TypeScriptMarcin Wanago Blog - JavaScript, both frontend and backend
Factory Method
Logo
Logo