Factory Design Pattern: Promotes flexibility & scalability

Design patterns are essential tools for building robust, maintainable, and scalable applications. Understanding and effectively utilizing design patterns can set you apart in frontend interviews. In this article, we will explore the Factory Design Pattern, a powerful pattern that promotes flexible and scalable object creation.

Factory Design Pattern

The Factory Design Pattern is a creational design pattern that provides a way to create objects without specifying the exact class of the object that will be created. It defines an interface for creating an object but allows subclasses to alter the type of objects that will be created.

class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  displayInfo() {
    console.log(`Car: ${this.make} ${this.model}, Year: ${this.year}`);
  }
}

class Truck {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  displayInfo() {
    console.log(`Truck: ${this.make} ${this.model}, Year: ${this.year}`);
  }
}

class VehicleFactory {
  static createVehicle(type, make, model, year) {
    switch (type) {
      case 'car':
        return new Car(make, model, year);
      case 'truck':
        return new Truck(make, model, year);
      default:
        throw new Error('Vehicle type not supported.');
    }
  }
}

const car = VehicleFactory.createVehicle('car', 'Toyota', 'Corolla', 2020);
const truck = VehicleFactory.createVehicle('truck', 'Ford', 'F-150', 2019);

car.displayInfo(); // Output: Car: Toyota Corolla, Year: 2020
truck.displayInfo(); // Output: Truck: Ford F-150, Year: 2019

Why is the Factory Pattern Important?

  1. Encapsulation: The Factory Pattern encapsulates the creation logic of objects, providing a single point of management for the instantiation process. This leads to cleaner and more maintainable code.
  2. Scalability: By centralizing the object creation process, the Factory Pattern makes it easier to scale and extend your application. Adding new types of objects requires minimal changes to the existing code.
  3. Flexibility: The Factory Pattern allows for the creation of different types of objects based on input parameters. This flexibility makes it easy to adapt the code to changing requirements.
  4. Decoupling: It decouples the client code from the actual instantiation process, making it easier to modify the object creation logic without affecting the rest of the application.

Real-Time Example: Shape Factory

class Circle {
  constructor(radius) {
    this.radius = radius;
  }

  draw() {
    console.log(`Drawing a Circle with radius ${this.radius}`);
  }
}

class Square {
  constructor(side) {
    this.side = side;
  }

  draw() {
    console.log(`Drawing a Square with side ${this.side}`);
  }
}

class ShapeFactory {
  static createShape(type, size) {
    switch (type) {
      case 'circle':
        return new Circle(size);
      case 'square':
        return new Square(size);
      default:
        throw new Error('Shape type not supported.');
    }
  }
}

const circle = ShapeFactory.createShape('circle', 5);
const square = ShapeFactory.createShape('square', 4);

circle.draw(); // Output: Drawing a Circle with radius 5
square.draw(); // Output: Drawing a Square with side 4

Explanation of the Example

Shape Classes:

  • Circle and Square are classes representing different shapes. Each class has a constructor to initialize its properties and a draw method to display the shape.

ShapeFactory Class:

  • The ShapeFactory class has a static method createShape that takes the type of shape and its size as parameters.
  • The method uses a switch statement to determine which shape class to instantiate based on the type parameter.
  • If the type is ‘circle’, it returns a new Circle instance. If the type is ‘square’, it returns a new Square instance. If the type is unsupported, it throws an error.

Using the Factory:

  • Two shapes, circle and square, are created using the ShapeFactory.createShape method.
  • The draw method is called on each shape to display its information.

Importance in Real-World Applications

The Factory Pattern is widely used in real-world applications for creating objects in a flexible and scalable manner. It is particularly useful in scenarios where the exact types of objects may not be known until runtime. By using the Factory Pattern, you can ensure that your code is modular, easy to extend, and less prone to errors.