Design Patterns — Creational - Singleton, Factory Method, Abstract Factory, Builder, Prototype
The 5 GoF creational patterns, in one breath:
| Pattern | One-line job | The question it answers |
|---|---|---|
| Singleton | Exactly one instance, global access | "How do I guarantee only one?" |
| Factory Method | A method subclasses override to choose the class | "Which subclass do I instantiate?" |
| Abstract Factory | A family of related products built together | "How do I keep a kit consistent?" |
| Builder | Build a complex object step by step | "Too many constructor args?" |
| Prototype | Create new objects by cloning an existing one | "New object is like this one?" |

1. Singleton
WHY: Some resources are inherently single — a config registry, a logging hub, a connection pool. Two copies would cause inconsistent state.
HOW (derive from first principles):
- To prevent others making instances → make the constructor
private. - To still give one out → a
staticmethod returns it. - To store it → a
staticfield holds the single instance.
class Logger {
private static Logger instance; // the one slot
private Logger() {} // nobody else can `new`
public static Logger getInstance() { // global access point
if (instance == null) // lazy: build on first use
instance = new Logger();
return instance;
}
}Why instance == null check? So we build lazily (only when first needed) and only once.
2. Factory Method
WHY: A Dialog knows it needs a button, but a WindowsDialog needs a Windows button and a WebDialog needs an HTML button. The base class shouldn't new WindowsButton().
HOW: Replace the direct new with a call to an overridable method.
abstract class Dialog {
abstract Button createButton(); // <-- factory method (the hook)
void render() {
Button b = createButton(); // base logic, no concrete class!
b.onClick(); b.draw();
}
}
class WindowsDialog extends Dialog {
Button createButton() { return new WindowsButton(); }
}Why is render() in the base class? Because the workflow is shared; only the product choice varies. That's the whole point — vary one decision via subclassing.
3. Abstract Factory
WHY: Factory Method makes one product. But a Windows UI needs Windows buttons AND checkboxes AND menus — they must match. Abstract Factory groups several factory methods so the whole kit is consistent.
interface GUIFactory { // the family
Button createButton();
Checkbox createCheckbox();
}
class WinFactory implements GUIFactory {
public Button createButton() { return new WinButton(); }
public Checkbox createCheckbox() { return new WinCheckbox(); }
}
// client takes a GUIFactory, never knows which OSWhy an object (factory) not subclassing? Because you swap the whole family at runtime by passing a different factory object. Factory Method varies by subclass; Abstract Factory varies by composition.
4. Builder
WHY: A constructor with 8 optional parameters → new Pizza(true,false,true,...) is unreadable ("telescoping constructors"). Builder names each step.
Pizza p = new Pizza.Builder()
.size("L")
.addCheese()
.addOlives()
.build(); // build() returns the finished, validated objectWhy build() at the end? So the object is immutable and fully validated only when assembly completes — no half-built objects leak out.
5. Prototype
WHY: When construction is expensive (heavy DB load, config parsing) or you only have a runtime object and want a duplicate, clone it.
interface Shape { Shape clone(); }
class Circle implements Shape {
int r;
public Shape clone() { Circle c = new Circle(); c.r = this.r; return c; }
}Recall Feynman: explain to a 12-year-old
Imagine a toy factory. Instead of building each toy with your bare hands every time (new), you use machines.
- Singleton: one special vending machine in the whole school — everyone uses that same one.
- Factory Method: a machine with a slot; a kid decides whether a car or a robot pops out.
- Abstract Factory: a machine that always gives a matching set — red car with red garage, never a mismatch.
- Builder: a sandwich shop where you say "bread, then cheese, then done!" step by step.
- Prototype: a photocopier — you have one drawing and press copy to get more.
Flashcards
What problem do creational patterns solve?
How does a Singleton prevent external instantiation?
private and exposing a static getInstance().Why is the naive lazy Singleton not thread-safe?
instance == null check and each create an instance.Best thread-safe lazy Singleton idiom in Java?
static final field).Factory Method varies the product by ___?
Abstract Factory varies the product family by ___?
Key difference: Factory Method vs Abstract Factory?
What pain does Builder cure?
build().Why must Prototype often use deep copy?
When prefer Prototype over a constructor?
Why is Singleton sometimes an anti-pattern?
Connections
- Design Principles — patterns are SOLID in action (esp. Open/Closed and Dependency Inversion).
- Factory Method is a special case used inside Abstract Factory.
- Builder vs Prototype — build fresh vs copy existing.
- Singleton often combined with Abstract Factory (one global factory).
- Structural Patterns and Behavioral Patterns — the other two GoF categories.
- Dependency Injection — modern alternative to Singleton.
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Creational patterns ka core idea simple hai: jab bhi aap seedha new SomeClass() likhte ho, aapka code us concrete class ke saath chipak jaata hai. Kal ko agar aapko doosri class chahiye, ya sirf ek hi shared instance chahiye, ya bahut saare optional fields ke saath object banana hai — to har jagah new change karna padega. In patterns ka kaam hai ek deewaar khadi karna "mujhe kya object chahiye" aur "wo banta kaise hai" ke beech. Construction ka logic ek hi jagah rahta hai.
Paanchon ko ek line mein yaad rakho: Singleton = poore program mein sirf ek hi instance (jaise ek hi config object). Factory Method = base class ek method deti hai jise subclass override karke decide karti hai kaunsi class banegi. Abstract Factory = ek poora matching family banata hai — Windows button ke saath Windows checkbox, mismatch kabhi nahi. Builder = jab constructor mein 8 arguments ho jaayein to step-by-step .addCheese().build() style mein object banao. Prototype = naya object banane ke bajaye purane ko clone() kar lo.
Sabse common galti Singleton mein hoti hai — log sochte hain naive lazy version thread-safe hai, par do threads ek saath null check pass karke do instance bana dete hain; iska fix hai holder idiom. Prototype mein dhyaan rakho ki shallow copy nested objects share kar leti hai, isliye deep copy chahiye. Aur yaad rakho: Singleton zyada use karna anti-pattern ban jaata hai kyunki wo global mutable state hai — testing mushkil ho jaati hai, isliye Dependency Injection prefer karo.