Factory Method Design Pattern in JavaScript

1. Definition

The Factory Method Design Pattern is a creational pattern that provides an interface for creating objects in a super class, but allows subclasses to alter the type of objects that will be created.

2. Problem Statement

Consider a UI library. This library has a base Dialog class, and depending on the platform (e.g., Web, Windows, MacOS), it needs to render different types of buttons. Directly embedding platform-specific button classes into the Dialog would make the Dialog class complicated and intertwined with platform-specific details.

3. Solution

The Factory Method pattern solves this by defining a separate method for creating the Button object. Subclasses can then override this method to produce a platform-specific button, keeping platform-specific code separate from the Dialog class.

4. Real-World Use Cases

1. A payment gateway that provides different payment method implementations based on the country or region.

2. UI libraries where component rendering varies based on platform or theme.

3. An application that needs to support multiple database systems and must provide database connection objects based on the DB configuration.

5. Implementation Steps

1. Define an interface that declares a factory method.

2. Let subclasses decide which class to instantiate and implement the factory method to return an instance of that class.

6. Implementation in JavaScript

// Step 1: Product interface
class Button {
  render() {}
}
// Concrete Products
class WebButton extends Button {
  render() {
    return "Web Button";
  }
}
class WindowsButton extends Button {
  render() {
    return "Windows Button";
  }
}
// Creator class with factory method
class Dialog {
  createButton() {
    throw new Error("Abstract method!");
  }
  render() {
    const button = this.createButton();
    return button.render();
  }
}
// Concrete Creators
class WebDialog extends Dialog {
  createButton() {
    return new WebButton();
  }
}
class WindowsDialog extends Dialog {
  createButton() {
    return new WindowsButton();
  }
}
// Client code
const webDialog = new WebDialog();
console.log(webDialog.render()); // Web Button
const windowsDialog = new WindowsDialog();
console.log(windowsDialog.render()); // Windows Button

Output:

Web Button
Windows Button

Explanation:

1. Button is the product interface, and WebButton & WindowsButton are concrete products.

2. The Dialog class acts as the creator, with a factory method createButton().

3. Subclasses WebDialog and WindowsDialog override the createButton method to return platform-specific buttons.

4. The render method in the Dialog class creates a button using the factory method and then invokes the render method of the button.

5. The client code creates instances of concrete dialogs (WebDialog and WindowsDialog) and calls their render methods.

7. When to use?

Use the Factory Method pattern when:

1. A class cannot anticipate the class of objects it needs to create.

2. A class wants its subclasses to decide which objects to create.

3. The process of creating objects should be isolated from the utilization of these objects.


Comments