Creational Design Patterns

Direct new calls are convenient, but they put configuration, lifecycle, and instance reuse in the hands of every caller. That works for tiny scripts, but it becomes painful once object creation starts carrying policy.

The Core Problem: Over-Reliance on new

When the client code is responsible for both configuring and instantiating a dependency, creation logic leaks everywhere.

  • Code duplication: every caller needs to know constructor arguments and setup order.
  • Modification fragility: if the constructor changes, every direct new site becomes a change point.
  • Resource inefficiency: repeated instantiation can waste memory, sockets, or connection slots.

The deeper issue is that creation policy is now spread across the codebase. A small constructor tweak can turn into a broad edit storm.

The Solution: Separate Creation from Usage

Creational patterns move creation into a dedicated object or method, so callers ask for what they need instead of assembling every dependency themselves.

[Client Code]  ->  [Creational Pattern Agent]  ->  [Concrete Instance]

This keeps the call site small, and it gives the system a single place to change when construction rules evolve.

Pattern Cheat Sheet

| Pattern | Intuition | Best Fit | | --- | --- | --- | | Singleton | One shared manager for the whole process | Shared resources like connection pools | | Factory / Factory Method | Pick the right object without exposing the creation logic | Parser selection, handler routing | | Builder | Assemble a complex object step by step | Objects with many optional settings | | Abstract Factory | Create related object families together | Theme-aware UI kits, cross-platform families | | Prototype | Clone an existing object instead of creating from scratch | Expensive blueprints, repeated templates |

Why This Matters

The lesson is not “always avoid new.” The lesson is to make creation deliberate.

  • Use Builder when a constructor starts turning into a parameter maze.
  • Use Singleton when one shared instance should coordinate access to a limited resource.
  • Use Factory when callers should not know which concrete class they are getting.
  • Use Abstract Factory when you need a family of related objects that must stay compatible.
  • Use Prototype when copying an initialized object is cheaper than reconstructing it.

Lab 1: Constructor Explosion Simulator

Toggle the DatabaseConnection options below and watch how quickly the constructor matrix grows. Then collapse the mess into a single fluent builder.

Lab 2: Connection Pool Exhaustion Sandbox

Run 100 virtual requests through a raw constructor path and then through a singleton-backed path. The difference is the whole lesson.

Lab 3: Structural Matching Challenge

Match each design scenario to the pattern that solves it. The goal is to learn the “why” behind each pattern, not just the name.

Creational Design Patterns

Constructor pressure, lifecycle control, and pattern selection

Use these three scenarios to feel why `new` becomes a liability and why factories, builders, and singletons exist as architectural escape hatches.

Exercise 1

The Constructor Explosion Simulator

Toggle optional connection settings to watch the overload matrix expand, then collapse it into a single fluent builder.

DatabaseConnection options
Active flags
5
Constructor count
32
Current view
Telescoping
Generated constructors
DatabaseConnection()
DatabaseConnection(boolean useSSL)
DatabaseConnection(int connectionTimeout)
DatabaseConnection(boolean useSSL, int connectionTimeout)
DatabaseConnection(int maxPoolSize)
DatabaseConnection(boolean useSSL, int maxPoolSize)
DatabaseConnection(int connectionTimeout, int maxPoolSize)
DatabaseConnection(boolean useSSL, int connectionTimeout, int maxPoolSize)
DatabaseConnection(String readReplicaHost)
DatabaseConnection(boolean useSSL, String readReplicaHost)
+ 22 more overloads
new DatabaseConnection(
  useSSL,
  connectionTimeout,
  maxPoolSize,
  readReplicaHost,
  enableLogging
);
Constructor matrix waiting

Toggle configuration flags to see the overload count explode, then switch to the Builder view.

Active flags
5
Constructor count
32
View
Telescoping
  1. Start with the raw constructor approach.
  2. The count grows as you add more optional flags.
Exercise 2

Connection Pool Exhaustion Sandbox

Compare raw instantiation with a singleton-managed connection while 100 virtual requests hit the database.

Request handler
function handleRequest() {
  const db = new DatabaseConnection();
  db.query("SELECT 1");
}
Virtual requests
100
Live connections
100
DB status
FATAL
Network chart
slot exhaustion
Postgres saturates as every request opens a fresh connection.
Traffic sandbox awaiting run

Simulate 100 requests to see how raw instantiation exhausts the database or how a singleton protects it.

Connection policy
raw new per request
Expected DB state
unknown
  1. Choose raw instantiation or singleton reuse.
  2. Run the traffic simulator to inspect the connection graph.
Exercise 3

Structural Matching Challenge

Match each architectural description to the creational pattern that solves it. Drag a tile onto a prompt or tap first and then tap the target card.

Prompt board
Pattern bank
Answer map
0/3 placed
ui-family
unassigned
clone-blueprint
unassigned
payload-parser
unassigned
Matching board ready

Drag the pattern tiles onto the prompts or tap a tile and then tap a prompt card.

Matches
0/3 placed
Pattern bank
all available
  1. Each prompt has a single correct pattern.
  2. Every answer should map to the pattern that solves the architectural breakdown.