Web Development

Enhancing Code Reusability with the Factory Pattern

By encapsulating object creation logic, the Factory pattern promotes code reusability and simplifies the process of creating complex objects.

By Laxaar Engineering Team Mar 7, 2024 3 min read
Enhancing Code Reusability with the Factory Pattern

Scattered new calls throughout your codebase are a maintenance trap: change one constructor signature and you're hunting down every call site. The Factory pattern solves this by pulling object creation into one place. By encapsulating that logic, it simplifies building complex objects and makes the code easier to extend without touching existing callers. This post covers two JavaScript forms of the pattern, Factory Functions and Abstract Factories, and shows how each one tightens reusability.

Understanding the Factory Pattern

The Factory pattern is one of the original Gang of Four creational patterns. The core idea is simple: don't let callers call new directly. Instead, they ask a factory for an object and get back whatever concrete type is appropriate. That indirection is small, but it means you can swap implementations, add logging, or enforce invariants in one place rather than across every call site.

Key Components of the Factory Pattern

  • Factory: The central component responsible for creating objects based on given parameters or conditions.
  • Product: The objects created by the factory. These can be of various types, but they typically share a common interface or base class.

Implementing Factory Functions in JavaScript

In JavaScript, a factory function is just a regular function that returns a new object. No classes required. You pass in the parameters that determine what you need, and the function handles the rest.

Example of a Fact

function createCar(type) {
    switch (type) {
        case 'sedan':
            return new Sedan();
        case 'suv':
            return new SUV();
        default:
            throw new Error('Invalid car type');
    }
}

const myCar = createCar('sedan');

The createCar function is the only place that knows about Sedan and SUV. Everything else just passes a string and gets a car back. Add a new type? One switch case. No hunt across the codebase.

Advantages of Factory Functions

  • Encapsulation. All creation logic lives inside the factory. Callers don't touch constructors directly, so internal changes stay internal.
  • Abstraction. The caller asks for an object by intent, not by class name. That's a meaningful boundary.
  • Flexibility. Adding a new type means adding a new branch in one function, not editing every call site in the project.

Abstract Factory Pattern

Factory Functions handle individual objects well. The Abstract Factory pattern takes a step further: it provides an interface for creating entire families of related or dependent objects. Use it when your system has multiple interrelated components that must stay consistent with each other.

Example of an Abstract Factory

class CarFactory {
    createEngine() {
        throw new Error('Method not implemented');
    }

    createTire() {
        throw new Error('Method not implemented');
    }
}

class SedanFactory extends CarFactory {
    createEngine() {
        return new SedanEngine();
    }

    createTire() {
        return new SedanTire();
    }
}

class SUVFactory extends CarFactory {
    createEngine() {
        return new SUVEngine();
    }

    createTire() {
        return new SUVTire();
    }
}

const sedanFactory = new SedanFactory();
const suvFactory = new SUVFactory();

const sedanEngine = sedanFactory.createEngine();
const suvTire = suvFactory.createTire();

CarFactory declares the contract: every vehicle family must supply an engine and a tire. SedanFactory and SUVFactory each fulfill that contract with their own parts. Swap one factory for the other and the rest of the system doesn't notice. It's still calling the same two methods.

Benefits of Abstract Factories

  • Consistent families. Because one factory produces all the related parts, mismatched combinations (a SedanEngine inside an SUVFactory build) can't happen.
  • Clean client code. The caller holds a reference to a factory, not to a list of concrete classes. The factory surface area is intentionally small.
  • Easy substitution. Switching from SedanFactory to SUVFactory is a one-line change. Every downstream object updates automatically.

Conclusion

Factory Functions and Abstract Factories address the same root problem from different angles. Factory Functions are the right starting point for most projects. Abstract Factories pay off when you're managing families of related objects that need to stay consistent with each other. Both patterns push creation logic behind an interface, which means the rest of your code doesn't care how objects get built. That separation is what keeps large JavaScript codebases from becoming fragile.

Working on something like this?

Get a fixed scope, timeline, and price within one business day — no obligation.

Factory PatternCode ReusabilityObject Creation LogicSoftware Design PatternsObject-Oriented Design
Grow your business with us

Take your business to the next level.

Tell us what you're building. We'll come back inside one business day with a fixed scope, timeline, and team — or an honest “this isn't a fit”.

ENGINEERING PHILOSOPHY

Code is useless if it's not comprehensible to those who maintain it. We write code the next person can actually understand.