All topics
Patternsintermediate

Factory Pattern

Using a function or method to create and return objects, encapsulating the object-creation logic away from the calling code.

A factory is a function that creates and returns an object, hiding how it is built.

A factory function is like ordering a 'sandwich' from a specific sandwich-shop counter rather than personally choosing and assembling every individual ingredient yourself — you describe roughly what you want, and the counter (factory) decides internally exactly how to build the specific item, handing you a finished product without you needing to know or care about its internal assembly steps.

Key Concepts

1
    function createUser(name, role) {
      return {
        name,
        role,
        canEdit: () => role === 'admin' || role === 'editor'
      };
    }
2
    const u = createUser('Asha', 'admin');
3
Against new and a class.
    no `new` to forget
    no `this` to get wrong
    the return type can vary
    privacy through closures, free
newthis
4
    // the caller cannot break it
    const u = createUser('Asha');       // works
    const u = new User('Asha');         // forgetting new used to
                                        // write to the global object
5
Returning different types is the pattern's real use.
    function createParser(format) {
      switch (format) {
        case 'json': return { parse: (s) => JSON.parse(s) };
        case 'csv':  return { parse: (s) => parseCsv(s) };
        default:     throw new Error(`unknown format ${format}`);
      }
    }
unknown format ${format}
6
The caller asks for a parser and does not know which one it got — which is the decoupling.
7
Privacy comes free with closures.
    function createAccount(initial) {
      let balance = initial;                  // private
      return {
        deposit: (n) => balance += n,
        get balance() { return balance; }
      };
    }
8
The trade against classes. Each factory call creates new function objects for every method; a class puts them on the prototype, shared.
9
    10,000 factory objects  -> 10,000 copies of each method
    10,000 class instances  -> one copy on the prototype
10
For a handful of objects it does not matter. For many, it does — and that is the main argument for classes in JavaScript.
11
Factory functions in practice. React hooks, Express middleware, most Node libraries, and any API where new would be noise.
new
12
And the naming convention worth following. createX rather than makeX or a bare noun, so the call site says what happens:
createXmakeX
13
    const parser = createParser('json');    // clearly constructing
    const parser = parser('json');          // unclear
14
What the interviewer is probing.1. "What does a factory give you over a constructor?" Probing: the advantages. Stalls: "It is the same." Moves up: a name, the freedom to return a subtype or a cached instance, and no requirement for new.
15
2. "Why do factories suit JavaScript particularly?" Probing: the language fit. Stalls: "They do not." Moves up: closures give private state without classes, so a factory returning an object with methods is both simpler and genuinely encapsulated.
16
3. "What is the memory trade?" Probing: honesty. Stalls: "None." Moves up: methods created per instance in a closure are not shared on a prototype, which matters only at very high instance counts.
17
4. "How would you choose an implementation at runtime?" Probing: the use case. Stalls: "With if statements everywhere." Moves up: a factory taking the discriminator and returning the right implementation, so callers depend on the shape not the choice.