JavaScript Factory Pattern


What is the Factory Pattern in JavaScript?

The Factory 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 objects and allows subclasses to alter the type of objects that will be created.


What are the benefits of using the Factory Pattern?

Benefits of the Factory Pattern include:

  • Decoupling: It decouples the object creation logic from the actual code that uses the objects, making the codebase more flexible and easier to maintain.
  • Single Responsibility Principle: The Factory Pattern adheres to the single responsibility principle by separating object creation from the business logic.
  • Flexibility: It allows for the creation of different types of objects through a common interface, facilitating easy changes to the object creation process without modifying existing code.

Can you provide a simple example of the Factory Pattern?

Here's a basic example of a Factory Pattern that creates different types of vehicles:


function VehicleFactory() {
  return {
    createVehicle: function(type) {
      switch (type) {
        case 'car':
          return new Car();
        case 'truck':
          return new Truck();
        default:
          throw new Error('Unknown vehicle type');
      }
    }
  };
}

function Car() {
  this.type = 'Car';
}

function Truck() {
  this.type = 'Truck';
}

const factory = VehicleFactory();
const myCar = factory.createVehicle('car');
const myTruck = factory.createVehicle('truck');

console.log(myCar.type); // Car
console.log(myTruck.type); // Truck

How can you implement a Factory Pattern using ES6 classes?

You can implement the Factory Pattern using ES6 classes to create different types of objects:


class Vehicle {
  constructor(type) {
    this.type = type;
  }
}

class Car extends Vehicle {
  constructor() {
    super('Car');
  }
}

class Truck extends Vehicle {
  constructor() {
    super('Truck');
  }
}

class VehicleFactory {
  createVehicle(type) {
    switch (type) {
      case 'car':
        return new Car();
      case 'truck':
        return new Truck();
      default:
        throw new Error('Unknown vehicle type');
    }
  }
}

const factory = new VehicleFactory();
const myCar = factory.createVehicle('car');
const myTruck = factory.createVehicle('truck');

console.log(myCar.type); // Car
console.log(myTruck.type); // Truck

What is the difference between the Factory Pattern and the Singleton Pattern?

The Factory Pattern focuses on creating objects and returning them based on certain parameters, while the Singleton Pattern restricts a class to a single instance and provides a global point of access to that instance. The Factory Pattern can create multiple instances, whereas the Singleton Pattern ensures only one instance exists.


// Factory Pattern
const factory = VehicleFactory();
const car1 = factory.createVehicle('car');
const car2 = factory.createVehicle('car');
console.log(car1 !== car2); // true (Different instances)

// Singleton Pattern
const Singleton = (function() {
  let instance;

  function createInstance() {
    return { name: 'Singleton' };
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const singleton1 = Singleton.getInstance();
const singleton2 = Singleton.getInstance();
console.log(singleton1 === singleton2); // true (Same instance)

How does the Factory Pattern facilitate testing?

The Factory Pattern can improve testing by allowing you to create mock objects or substitute different implementations of objects during tests. By abstracting the creation of objects, you can inject dependencies and easily swap out implementations for testing purposes.


// Mock object example
class MockVehicle {
  getType() {
    return 'Mock Vehicle';
  }
}

class MockVehicleFactory {
  createVehicle() {
    return new MockVehicle();
  }
}

const mockFactory = new MockVehicleFactory();
const mockVehicle = mockFactory.createVehicle();
console.log(mockVehicle.getType()); // Mock Vehicle

Can you combine the Factory Pattern with other design patterns?

Yes, the Factory Pattern can be combined with other design patterns such as the Singleton Pattern, Strategy Pattern, or Observer Pattern. This combination can enhance the flexibility and scalability of your code by leveraging the strengths of multiple patterns.


// Example combining Factory and Strategy patterns
class Car {
  drive() {
    console.log('Driving a car');
  }
}

class Truck {
  drive() {
    console.log('Driving a truck');
  }
}

class VehicleFactory {
  createVehicle(type) {
    switch (type) {
      case 'car':
        return new Car();
      case 'truck':
        return new Truck();
      default:
        throw new Error('Unknown vehicle type');
    }
  }
}

const factory = new VehicleFactory();
const vehicle = factory.createVehicle('car');
vehicle.drive(); // Driving a car

What are some common mistakes to avoid when implementing the Factory Pattern?

Common mistakes include:

  • Overcomplicating the factory function by adding too many parameters or responsibilities.
  • Not adhering to the single responsibility principle, leading to factories that handle multiple types of objects without clear organization.
  • Forgetting to return the created objects or improperly managing the instances returned by the factory.
  • Neglecting to handle errors or edge cases when creating objects, leading to unhandled exceptions.
Ads