Mastering the Factory Pattern in JavaScript

The factory pattern is a fundamental design pattern in JavaScript used for creating objects. It encapsulates the object creation process, providing a centralized place for creating instances without exposing the instantiation logic. This chapter delves into the factory pattern, covering its basic principles, advanced techniques, practical examples, and the benefits it offers to JavaScript developers.

Basics of Factory Pattern

Understanding Factory Functions

Factory functions are simple functions in JavaScript that produce and return new objects. They encapsulate the object creation process, making it easier to manage and reuse.

Example:

				
					function createPerson(name, age) {
  return {
    name: name,
    age: age,
    greet: function() {
      return `Hello, my name is ${this.name}.`;
    }
  };
}

const person1 = createPerson('John', 30);
console.log(person1.greet()); // Output: Hello, my name is John.

				
			

This code defines a factory function named createPerson that takes name and age parameters and returns an object representing a person. The returned object has properties name and age, and a method greet that returns a greeting message using the person’s name.

Simple Factory Pattern

The simple factory pattern centralizes object creation logic within a single function. It abstracts the process of object instantiation and shields the client from knowing the specifics of the creation process.

Example:

				
					function createShape(type) {
  if (type === 'circle') {
    return {
      type: 'circle',
      radius: 10
    };
  } else if (type === 'rectangle') {
    return {
      type: 'rectangle',
      width: 20,
      height: 30
    };
  }
}

const circle = createShape('circle');
const rectangle = createShape('rectangle');

				
			

Here, createShape is a factory function that creates different shapes based on the type parameter passed to it. It returns an object representing either a circle or a rectangle with specific properties like type, radius, width, and height.

Advanced Concepts in Factory Pattern

Factory Method Pattern

The factory method pattern extends the factory pattern by defining an interface for creating objects in subclasses. Each subclass can override the factory method to create objects of different types.

Example:

				
					class Shape {
  draw() {
    console.log('Drawing a shape');
  }
}

class Circle extends Shape {
  draw() {
    console.log('Drawing a circle');
  }
}

class Rectangle extends Shape {
  draw() {
    console.log('Drawing a rectangle');
  }
}

class ShapeFactory {
  createShape(type) {
    if (type === 'circle') {
      return new Circle();
    } else if (type === 'rectangle') {
      return new Rectangle();
    }
  }
}

const shapeFactory = new ShapeFactory();
const circle = shapeFactory.createShape('circle');
const rectangle = shapeFactory.createShape('rectangle');

				
			

In this example, ShapeFactory is a factory class with a createShape method that creates different shapes based on the type parameter. Depending on the type, it returns instances of either Circle or Rectangle classes, which are subclasses of Shape.

Abstract Factory Pattern

The abstract factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It allows for the creation of families of objects that are designed to work together.

Example:

				
					class Button {
  render() {
    console.log('Rendering a button');
  }
}

class Checkbox {
  render() {
    console.log('Rendering a checkbox');
  }
}

class MaterialUIFactory {
  createButton() {
    return new Button();
  }

  createCheckbox() {
    return new Checkbox();
  }
}

class AntDesignFactory {
  createButton() {
    return new Button();
  }

  createCheckbox() {
    return new Checkbox();
  }
}

const materialUIFactory = new MaterialUIFactory();
const antDesignFactory = new AntDesignFactory();
const materialUIButton = materialUIFactory.createButton();
const antDesignButton = antDesignFactory.createButton();

				
			

Here, MaterialUIFactory and AntDesignFactory are abstract factory classes that provide methods for creating UI components specific to their respective UI libraries. Each factory class has methods like createButton and createCheckbox that return instances of Button and Checkbox classes.

Practical Applications of Factory Pattern

Creating Database Connection Objects

The factory pattern is commonly used in scenarios where multiple database connections need to be created based on different configurations.

Example:

				
					function createDatabaseConnection(config) {
  if (config.type === 'mysql') {
    return new MySQLConnection(config);
  } else if (config.type === 'mongodb') {
    return new MongoDBConnection(config);
  }
}

				
			

In this code, createDatabaseConnection is a factory function that creates database connection objects based on the configuration provided. It takes a config object as a parameter, which contains information about the type of database to connect to.

  • If the type property of the config object is 'mysql', the function creates a new instance of MySQLConnection using the provided config.
  • If the type property is 'mongodb', it creates a new instance of MongoDBConnection with the provided config.

This factory function abstracts the process of creating database connections, allowing the client code to create database connections without needing to know the specifics of how each type of connection is established. It promotes code reuse and encapsulates the database connection logic, making the codebase more modular and maintainable.

This practical example demonstrates how the factory pattern can be applied to real-world scenarios to handle object creation based on different conditions or configurations.

Generating Random Data Objects

Factory functions can be employed to generate random data objects with predefined properties and values for testing purposes.

Example:

				
					function createRandomDataObject() {
  return {
    id: Math.floor(Math.random() * 1000),
    name: 'Random Name',
    age: Math.floor(Math.random() * 100),
    // Other properties...
  };
}

				
			

In this code, createRandomDataObject is a factory function that generates a random data object with predefined properties and random values. Each time this function is called, it returns a new object with a randomly generated id (between 0 and 999), a fixed name (‘Random Name’), and a randomly generated age (between 0 and 99).

This factory function is useful for creating mock data or generating test data for applications. It abstracts the process of generating random data objects, making it easy to create objects with consistent structure and randomized values.

By encapsulating the logic for generating random data objects within a factory function, the code becomes more modular and maintainable. Additionally, it promotes code reuse, as the same factory function can be used across different parts of the application to generate random data objects as needed.

The factory pattern in JavaScript offers a flexible and robust solution for object creation, allowing for encapsulation, abstraction, and customization. Whether it's a simple factory function or more advanced patterns like factory method or abstract factory, understanding and applying the factory pattern can lead to more efficient and maintainable code. By mastering the factory pattern, JavaScript developers can enhance their code architecture and design scalable and extensible applications. Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India