skip to content

Creational Patterns

Patterns that separate how an object is created from how it is used, so a system does not hard-code its own construction: Singleton, Factory Method, Abstract Factory, Builder, Prototype and Object Pool.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

page 1 of 2

What problem does the Abstract Factory design pattern solve, and what does it mean that it creates a "family" of objects?

level: juniorimportance: must knowfreq 72%

answer

  1. one method per product kind
  2. variants × kinds grid
  3. consistency enforced by construction
  4. concrete names only at composition root
  5. new kind ⇒ touch every factory

basics

~20 s

Abstract Factory gives you one interface with several creation methods that together produce a set of related objects. Client code asks the interface for parts and never names concrete classes, so swapping one factory swaps the whole matching set.

solid answer

~50 s

Abstract Factory declares an interface with one creation operation per product kind (e.g. createButton, createCheckbox, or createConnection/createStatementBuilder/createDialect). Each concrete factory implements all of them with one coherent variant — a "family". Client code is written against the abstract factory and the abstract product interfaces only, so it never mentions a concrete class name; the choice of family happens once, at composition time (config, startup wiring, dependency injection). Two benefits follow. First, substitutability: switching from the Dark family to the Light family, or Postgres to Oracle, is a single wiring change. Second, and more specific to this pattern, consistency: because one factory produces all the parts, the type system makes it hard to accidentally combine a Dark button with a Light checkbox. The cost is indirection and a rigid factory interface: adding a new product kind touches every factory implementation.

code

typescript · 21 lines
typescript
interface Button { render(): void }
interface Checkbox { render(): void }

interface GuiFactory {
  createButton(): Button
  createCheckbox(): Checkbox
}

class DarkFactory implements GuiFactory {
  createButton() { return new DarkButton() }
  createCheckbox() { return new DarkCheckbox() }
}

// Client depends on interfaces only.
function buildScreen(f: GuiFactory) {
  const parts = [f.createButton(), f.createCheckbox()]
  parts.forEach(p => p.render())
}

// Composition root — the only place a concrete class is named.
buildScreen(config.theme === 'dark' ? new DarkFactory() : new LightFactory())

go deeper

for a junior

State the intent: one interface with several creation methods, clients use interfaces only, swap the factory to swap the whole set. Give a UI-theme or database-driver example.

for a middle

Add the consistency guarantee (a single factory instance makes mixed-variant bugs unrepresentable) and name the composition root as the one place concrete classes appear.

for a senior

Discuss the variants × kinds grid, the asymmetric extensibility (cheap to add a variant, expensive to add a kind), and when a DI container or plain configuration is the simpler answer.

for a principal

Frame it as a decision about which axis of change you are buying flexibility on, note that the abstract factory interface becomes a published contract that is costly to evolve, and describe migration paths (registry, capability lookup) when the family stops being uniform.

### The vocabulary first - **Concrete class**: the actual implementation type you would name when constructing an object directly (`new DarkButton()`). - **Abstract product**: an interface or abstract type describing what a product *does* (`Button` with `render()` and `onClick()`), independent of how it is implemented. - **Concrete product**: an implementation of an abstract product belonging to one variant (`DarkButton`, `LightButton`). - **Product family**: a set of *different* product kinds that belong together and are meant to be used as a group — e.g. `{Button, Checkbox, ScrollBar}` all in the Dark variant, or `{Connection, QueryBuilder, SqlDialect}` all for Postgres. - **Abstract factory**: an interface declaring **one creation method per product kind** in the family. - **Concrete factory**: one implementation of that interface per variant, returning that variant's concrete products — but *declaring* the abstract product types as return types. ### The problem it addresses Without the pattern, code that needs several related objects hardcodes their concrete classes: ``` button = new DarkButton() checkbox = new DarkCheckbox() scrollbar= new LightScrollBar() // oops — wrong variant, compiles fine ``` Two separate pains appear: 1. **Coupling to concrete classes.** Every construction site must be edited to support a new variant, and the client can only be tested against real implementations. 2. **Family consistency.** Nothing prevents mixing variants. The bug above is silent: it type-checks, it runs, it just looks wrong (or, in a persistence example, produces SQL the connected database cannot parse). Abstract Factory collapses both problems into a single decision point: ``` interface GuiFactory { Button createButton() Checkbox createCheckbox() ScrollBar createScrollBar() } class DarkFactory implements GuiFactory { ... returns Dark* ... } class LightFactory implements GuiFactory { ... returns Light* ... } // client — knows GuiFactory, Button, Checkbox, ScrollBar and nothing else class Screen { Screen(GuiFactory f) { this.button = f.createButton(); this.check = f.createCheckbox(); } } ``` The concrete class names now appear in exactly one place: the **composition root** — the startup code that decides which factory to instantiate, typically from configuration, an environment variable, an OS check, or a dependency-injection container binding. ### Why "family" is the load-bearing word The pattern is not "a factory that is abstract". Its distinguishing property is the **cross-product structure**: variants × product kinds. Because a single object supplies every kind for one variant, the invariant *"all parts come from the same variant"* is enforced structurally rather than by discipline. That is the guarantee you cite when an interviewer asks why not just use several independent factories. ### The mechanism, step by step 1. Identify the product kinds that must vary **together**. 2. Extract an abstract product interface for each kind. 3. Declare the abstract factory with one creation method per kind. 4. Implement one concrete factory per variant. 5. Write clients against abstract types only. 6. Choose and inject the concrete factory once, at startup. ### Costs and edge cases - **Indirection tax.** Two extra type hierarchies (factories and products) for what used to be a constructor call. Not worth it for one variant, or when variants will never grow past one. - **Rigid interface.** Adding a *new product kind* (say `createSlider()`) forces a change in the abstract factory and in **every** concrete factory. The pattern is open for extension along the *variant* axis and closed-ish along the *product-kind* axis. This asymmetry is the classic senior follow-up. - **Parameterless creation.** Creation methods usually take no arguments so that clients stay ignorant of construction details; when products genuinely need runtime arguments, they must be threaded through the factory signature (and then every variant must accept them), which is where the design starts to strain. - **Cross-family objects.** Sometimes a product needs a sibling from the same family (a `DarkButton` needing a `DarkTheme`). Concrete factories can pass themselves or shared state to the products they build. - **Not a singleton requirement.** Concrete factories are often stateless and shared, but the pattern says nothing about lifecycle; that is a separate decision. ### Where you have already seen it JDBC-style database drivers (a driver yields connections, statements and metadata that all belong to one vendor), XML/DOM `DocumentBuilderFactory`, GUI look-and-feel toolkits, and cloud-SDK client builders that hand out a matched set of service clients for one provider or region.

  • If the only goal were removing `new` from the client, would Abstract Factory be the right choice?
    No. Any factory (Factory Method, a static creator, a DI container) removes `new`. Abstract Factory earns its extra structure only when several product kinds must vary together and mixing variants must be prevented.
  • Where should the decision of which concrete factory to use live?
    In the composition root — startup wiring, configuration reading, or DI container bindings — so exactly one place knows concrete class names and the rest of the codebase stays variant-agnostic.

A restaurant's set menu. You pick "the vegan menu" once; the kitchen then hands you a starter, a main and a dessert that all belong to that menu. You never assemble a vegan starter with a meat main by accident, because one decision produced the whole tray.

saying these in an interview costs you the question

  • Saying Abstract Factory is just "a factory with an interface" and never mentioning families or consistency.
  • Claiming it removes all coupling to concrete classes — the composition root must still choose one.
  • Letting client code downcast the returned abstract product back to a concrete type, which destroys the whole benefit.
  • Introducing it when there is exactly one variant and no realistic second one — pure speculative generality.
  • Confusing it with Builder (step-by-step construction of one complex object) or Prototype (cloning).

context

open as a page

What problem does the Builder design pattern solve, and how is it better than a constructor that takes many parameters?

level: juniorimportance: must knowfreq 78%

basics

~20 s

Builder replaces a long constructor argument list. You set values one named step at a time, skipping the ones you do not need, then call build() to get the finished object. It is easier to read and harder to mix arguments up.

open as a page

What problem do creational design patterns (Singleton, Factory Method, Abstract Factory, Builder, Prototype) solve, and what do they all have in common?

level: juniorimportance: must knowfreq 72%

basics

~20 s

They separate creating an object from using it. Instead of calling a concrete constructor directly, code asks something else to produce the object — so the system can change which class is built, and how, without editing every caller.

open as a page

What is the Factory Method design pattern, and what problem does it solve?

level: juniorimportance: must knowfreq 78%

basics

~20 s

Factory Method hides object creation behind an overridable method. Code that needs an object calls that method instead of naming a concrete class directly, and a subtype (or implementation) decides which concrete class actually gets built.

open as a page

What problem does the Object Pool creational pattern solve, and what is the acquire/use/release lifecycle of a pooled object?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Some objects are slow or costly to create — database connections, threads, sockets, large buffers. An Object Pool keeps a fixed set of them alive and ready. Callers borrow one, use it, then give it back instead of creating and destroying it each time.

open as a page

What problem does the Prototype creational design pattern solve, and how does it produce new objects?

level: juniorimportance: must knowfreq 55%

basics

~20 s

Prototype creates a new object by copying an existing, already-configured object instead of building one from scratch. You ask the existing instance to clone itself. It helps when construction is slow or the setup is long and fiddly.

open as a page

What problem does the Singleton design pattern solve, and how is it different from simply declaring a global variable?

level: juniorimportance: must knowfreq 82%

basics

~20 s

Singleton ensures a class has exactly one instance and one shared way to reach it. Unlike a plain global variable, the class hides its own constructor and creates the instance itself, so no other code can make a second one.

open as a page

How does the Abstract Factory pattern differ from the Factory Method pattern, in both intent and mechanism?

level: middleimportance: must knowfreq 80%

basics

~20 s

Factory Method has one creation method for one product kind and varies it by subclassing the creator. Abstract Factory is an object with several creation methods covering a whole family of related products, and you vary it by swapping which factory object you pass in.

open as a page

How does the Builder pattern let you create fully immutable objects with validated invariants, and why is that hard to achieve with a no-arg constructor plus setters?

level: middleimportance: must knowfreq 62%

basics

~20 s

The builder holds the values while you fill them in; the real object is created only once, at build(), through a private constructor. So the product needs no setters and can be immutable, and build() is a single place to check rules that involve several fields together.

open as a page

How do Factory Method and Abstract Factory differ in intent and structure, and how do you decide which one a design needs?

level: middleimportance: must knowfreq 68%

basics

~20 s

Factory Method is one overridable method on a class; a subclass decides which single product to create. Abstract Factory is a separate object with several creation methods that produce a whole family of related products that must match each other.

open as a page

How does the Factory Method pattern differ from a simple factory (a static or helper method that switches on a parameter to build objects)?

level: middleimportance: must knowfreq 66%

basics

~20 s

A simple factory is one method with a switch that picks the class; adding a type means editing that method. Factory Method is an overridable method — adding a type means adding a new subtype that overrides it, leaving existing code untouched.

open as a page

An Object Pool with a fixed maximum size receives an acquire request while every instance is already checked out. What policies can the pool apply, and how do you choose between them?

level: middleimportance: must knowfreq 66%

basics

~20 s

The pool can make the caller wait until someone returns an object (usually with a timeout), fail fast with an error, or — in a soft-limited pool — create a temporary extra instance. Waiting forever is the dangerous option: it can hang the whole system.

open as a page

Why must an Object Pool reset a borrowed object's state before or after each lease, and what goes wrong when the reset is incomplete?

level: middleimportance: must knowfreq 58%

basics

~20 s

Because the same object is reused by different callers. If one caller's leftover state — an open transaction, a half-filled buffer, a per-user setting — survives, the next caller silently inherits it. That causes wrong results and can leak one user's data into another user's request.

open as a page

When implementing a copy operation for the Prototype pattern, what is the difference between a shallow copy and a deep copy, and what bug does choosing wrongly cause?

level: middleimportance: must knowfreq 70%

basics

~20 s

A shallow copy duplicates the object's own fields, so reference fields still point at the same nested objects — original and copy share them. A deep copy also duplicates those nested objects. Choosing shallow wrongly means editing the copy silently changes the original.

open as a page

A Singleton creates its instance lazily on first call to its accessor. What can go wrong when several threads call that accessor at the same time, and which implementation strategies fix it?

level: middleimportance: must knowfreq 74%

basics

~20 s

Two threads can both see the field as empty and each create an instance, so you end up with two. Fix it by creating the instance eagerly at class load, or by guarding the check-and-create with a lock or a run-once primitive.

open as a page

Singleton is the most criticized creational pattern. What problems does the classic implementation cause, and how does a dependency-injection container provide the same single-instance guarantee without them?

level: seniorimportance: must knowfreq 62%

basics

~20 s

Classic Singleton hides a global variable behind a static accessor: callers reach for it directly, so dependencies are invisible, tests can't substitute it, and shared mutable state plus lazy initialization creates concurrency problems. A DI container keeps one instance per scope but injects it, so dependencies stay explicit and replaceable.

open as a page

Why is the Singleton pattern widely criticised, and how does injecting a single shared instance via dependency injection address those criticisms while still guaranteeing one instance?

level: seniorimportance: must knowfreq 70%

basics

~20 s

Singletons are global mutable state reached through a static call, so dependencies are invisible in signatures, state leaks between tests, and you cannot substitute a fake. Dependency injection keeps one shared instance but passes it in explicitly, so it stays visible and replaceable.

open as a page

How does the Builder pattern differ from Factory Method and Abstract Factory, and how would you decide which one a given creation problem calls for?

level: middleimportance: should knowfreq 55%

basics

~20 s

Factory Method and Abstract Factory answer "which class do I create?" and do it in one call. Builder answers "how do I assemble this one complicated object?" across many calls. Use a factory to hide the concrete type; use a builder for many optional parts.

open as a page

When would you choose Builder over a plain constructor or static factory, and when would Prototype beat both?

level: middleimportance: should knowfreq 55%

basics

~20 s

Use Builder when an object has many optional or order-dependent parts and a constructor would become a long, unreadable parameter list. Use Prototype when creating a fresh object is expensive or its configuration is easier to copy from an existing instance than to specify again.

open as a page

How does polymorphic creation via Factory Method support the Open/Closed Principle and the Dependency Inversion Principle?

level: middleimportance: should knowfreq 52%

basics

~20 s

Business logic calls an overridable creation method and uses only the product interface, so it never names a concrete class. New behaviour arrives as a new subtype (extension, no edits), and the logic depends on abstractions rather than on concrete implementations.

open as a page

What is a prototype registry, and when would you prefer registering configured prototypes over adding another factory or subclass?

level: middleimportance: should knowfreq 40%

basics

~20 s

A prototype registry is a lookup table from a key to a ready-made, configured object. Clients ask for a key and clone what comes back. You prefer it when new variants differ only in configuration, so adding one means adding data, not code.

open as a page

When implementing a Singleton, what are the trade-offs between creating the instance eagerly at startup versus lazily on first use?

level: middleimportance: should knowfreq 55%

basics

~20 s

Eager creation happens at startup: simple, thread-safe for free, and failures show up immediately — but you pay the cost even if the object is never used. Lazy creation defers the cost to first use, at the price of needing thread-safe initialization.

open as a page

You have an established Abstract Factory interface with several concrete factories in production. What happens when you need to add a brand-new product kind to the family, and how would you mitigate the cost?

level: seniorimportance: should knowfreq 52%

basics

~20 s

Adding a new product kind means adding a method to the factory interface, so every existing concrete factory must implement it. Adding a new variant is cheap; adding a new kind is expensive. Mitigations include default implementations, splitting the interface, or a registry keyed by product type.

open as a page

When is Abstract Factory the wrong choice, and what simpler alternatives cover the same need in a modern codebase with a dependency-injection container?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Skip it when there is only one variant, when the products do not have to match each other, or when objects need lots of runtime arguments. A DI container binding, a configuration switch at startup, or plain constructor injection usually covers the need with less machinery.

open as a page

The Gang of Four describe Builder as 'separate the construction of a complex object from its representation so that the same construction process can create different representations', with a Director driving an abstract Builder interface. How does that differ from the popular fluent nested-class builder, and when does the original form still matter?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The fluent builder mainly names optional parameters for one class. The original Builder has an interface with several implementations plus a Director that calls the steps in a fixed order, so one construction process can produce different outputs — for example the same document walk emitting HTML or plain text.

open as a page

In a builder, how do you guarantee that required parameters were actually supplied, and what are the trade-offs between checking in build() at runtime and using a staged (step) builder that enforces it at compile time?

level: seniorimportance: should knowfreq 32%

basics

~20 s

Simplest: take required values in the builder's constructor or factory method, and check the rest in build(), throwing if something is missing. Stronger: a staged builder, where each step returns a different type that only exposes the next required step, so forgetting one will not compile.

open as a page

What are the costs and failure modes of Factory Method, and when would you deliberately not use it?

level: seniorimportance: should knowfreq 40%

basics

~20 s

It adds a class hierarchy and indirection: more types to read, harder to see what actually gets created, and extension only via subclassing. Skip it when there's one implementation, when a plain function or injected dependency suffices, or when selection is data-driven.

open as a page

When would you choose Factory Method over Abstract Factory or Builder, and how do these three creational patterns differ?

level: seniorimportance: should knowfreq 58%

basics

~20 s

Factory Method varies one product through one overridable method. Abstract Factory groups several related products behind one interface so a whole family swaps together. Builder assembles one complex object step by step when it has many optional parts.

open as a page

In a system using an Object Pool, what is a "pool leak", how does it typically manifest in production, and what design and operational measures prevent or detect it?

level: seniorimportance: should knowfreq 54%

basics

~20 s

A leak is when code borrows an object from the pool and never returns it — usually because an exception skipped the return call. The pool slowly runs out of instances until every request hangs or times out, often long after deploy.

open as a page

When is applying the Object Pool pattern the wrong choice, and what alternatives address the same cost without pooling?

level: seniorimportance: should knowfreq 42%

basics

~20 s

Pool only things that are genuinely expensive to create, like connections or threads. Pooling ordinary in-memory objects on a garbage-collected runtime is usually slower and adds bugs: leaks, leftover state, and lock contention on the pool itself.

open as a page

showing 1–30 of 41