Creational
Step 5 in the OO & Low-Level Design path · 5 concepts · 0 problems
📘 Learn Creational from zero
Start from the problem. Normal object creation is new Car(). That looks harmless, but the keyword new hardwires the exact concrete class into the code that uses it. Creational patterns answer one question: how do we create objects without our code being rigidly glued to specific concrete classes — and without making construction itself a mess?
Analogy: a restaurant kitchen. A customer does not assemble their own burger. They give an order to a kitchen and receive a finished dish — they never touch the raw ingredients or know the recipe. If the chef swaps beef for a plant patty, the customer's experience is unchanged. The customer is decoupled from how the food is built. That separation between "what I want" and "how it is built" is the whole family of creational patterns.
Worked example. Suppose a game spawns enemies:
- Naive:
if (type == "orc") e = new Orc(); else if (type == "troll") e = new Troll();— this chain gets copy-pasted everywhere, and adding a Dragon means editing every site. (Centralizing it in one method is the Simple Factory idiom.) - Factory Method: declare an abstract
Enemy createEnemy()on a base spawner; each subclass (OrcSpawner,DragonSpawner) overrides it. Callers hold a baseSpawnerand writeEnemy e = spawner.createEnemy();, never naming a concrete enemy. Adding Dragon means one new subclass — callers are untouched.
Now imagine an Orc must always come with an Orc-themed weapon and shield, never a Troll's. Bundling those related products is Abstract Factory. If Orc construction took 50 mostly-optional fields, you would Builder it. If a fully configured exemplar already exists, you Prototype (clone) it. If only one global spawner may exist, that spawner is a Singleton.
Key insight: every creational pattern is one tactic for the same GoF goal — program to an interface, not an implementation, by centralizing and abstracting the new.
✨ Added by the guide to build intuition — not from the source course.
🎯 Guided practice
- Easy — Make a Logger a Singleton. Requirement: every part of an app must write to the same log buffer; two loggers would split the logs.
Step 1 — Spot the trigger: "exactly one, shared access" then Singleton.
Step 2 — Block other instantiation: make the constructor
privateso no caller can runnew Logger().Step 3 — Provide the single access point: a static
getInstance()returning the one stored instance — created on first call (lazy) or eagerly as astatic finalfield.Step 4 — Handle concurrency: if two threads call lazy
getInstance()at once, you can create two objects. Fix with eager init, the initialization-on-demand holder idiom (class-loading guarantees one), or double-checked locking on avolatilefield. Say this out loud — interviewers reliably probe thread safety, and "DCL withoutvolatile" is a classic trap.Takeaway: Singleton = private constructor + static accessor + a safely-published single instance.
- Medium — Build a cross-platform UI toolkit. Requirement: render a
Buttonand aCheckboxthat match the OS — all macOS, or all Windows, never mixed.Step 1 — Recognize the family: two related products (
Button,Checkbox) that must vary together by one theme then this is Abstract Factory, not a lone Factory Method.Step 2 — Define abstract products: interfaces
ButtonandCheckbox, with concretesMacButton/WinButtonandMacCheckbox/WinCheckbox.Step 3 — Define the abstract factory: interface
GUIFactorywithcreateButton()andcreateCheckbox(). Two implementations:MacFactoryreturns Mac products;WinFactoryreturns Win products. Since each factory only ever returns one family, mixing is impossible by construction.Step 4 — Wire it once: at startup pick
GUIFactory f = onMac ? new MacFactory() : new WinFactory();. The rest of the app callsf.createButton()/f.createCheckbox()and never references a concrete class.Step 5 — Verify the win: adding a Linux theme = one new factory plus its products, with zero changes to app code (Open/Closed Principle).
Takeaway: Abstract Factory groups several creation methods (each often a Factory Method) so whole families of products stay mutually consistent.
✨ Added by the guide — work these before the full problem set.