Explore Topics
π―
Intent
Ensure exactly one instance β and offer a global way to reach it.
π§ͺ Singleton Variant Lab β 4 variants Γ 4 scenarios
π App Startup: JVM boots, classes get loaded. No client has touched the singleton yet.
Eager Initialization
instances: 1
When created: Built at class load
thread-safe: β yesexception-safe: β no
Already constructed before main() runs.
Static Block Init
instances: 1
When created: Built in static block at class load
thread-safe: β yesexception-safe: β yes
Constructor runs inside try/catch β checked exceptions become RuntimeException.
Lazy Initialization
instances: 0
When created: Not yet built
thread-safe: βexception-safe: β
Singleton class loaded but the `instance` field is still null.
Bill Pugh Holder
instances: 0
When created: Holder class NOT loaded yet
thread-safe: β yesexception-safe: β
Outer class is loaded, but the nested Holder is deferred β true laziness.
| Property | Eager | Static Block | Lazy | Bill Pugh |
|---|---|---|---|---|
| Lazy? | β | β | β | β |
| Thread-safe? | β (JVM) | β (JVM) | β | β (JVM) |
| Exception handling? | β | β try/catch | caller sees | β in Holder |
| Performance | fastest | fastest | fastest (no sync) | fastest |
| Verdict | always-need | always + throws | teaching only | modern default β |
Pick a scenario above to see how each variant behaves. Toggle Matrix β Timeline for the two perspectives.
π―
Intent
Ensure exactly one instance β and offer a global way to reach it.
Singleton is a creational design pattern that guarantees a class has only one instance and provides a single global access point to that instance. It also encapsulates "just-in-time initialization" β the instance comes into existence on first use, not by anyone calling `new` from outside. The pattern actually solves two problems at once (uniqueness + access), which is exactly why it is sometimes criticized as an SRP violation: a class is taking on both its business responsibility and the responsibility of policing its own creation.
Key Ideas
- Hide the constructor (private) so nobody outside the class can call `new`.
- Hold the unique instance in a private static field.
- Expose a public static `getInstance()` that returns that one instance.
- Solves uniqueness AND access in one pattern β which is also the SRP complaint.
- Variants differ only in WHEN and HOW the instance is created.
Strengths
- β¦Guaranteed single instance across the whole JVM
- β¦Globally reachable without parameter-passing
- β¦Lazy variants delay heavy initialization
- β¦Centralizes control of a shared resource
Weaknesses
- β³Smuggles global state into the design
- β³Hides dependencies β callers don't see what they rely on
- β³Hard to unit-test (cannot mock the call to a static method)
- β³Mixes uniqueness concern with business logic (SRP debate)
Used in:Configuration manager, logger, thread pool, connection pool, and ID/account-number generators all need exactly one shared instance per process.
Code Snippets
Quiz
Intent Quiz
QUIZ 1/6Which statement best captures the GoF Intent of the Singleton pattern?
Diagrams
Practice
Drag each property to the Singleton variant it BEST describes. Each variant accepts exactly two properties.
EXERCISE 1/4Built at class load β wastes init cost if unused
Simplest reference, no synchronization needed
Wraps construction in try/catch for checked exceptions
Eager + exception handling, still not lazy
NOT thread-safe under concurrent first-time access
Textbook idiom for teaching lazy initialization
Uses a nested static Holder class
Lazy AND thread-safe by JVM guarantee β no synchronized
Eager Initialization
Static Block Initialization
Lazy Initialization
Bill Pugh (Holder Idiom)
Spot the bug β why is this NOT a real Singleton?
EXERCISE 2/4Click on the line you think contains the bug, then press Confirm.
Complete the Bill Pugh holder-idiom singleton
EXERCISE 3/4public class Config {
// Block external construction:
Config() { /* load config */ }
// The lazy, thread-safe holder:
private class Holder {
private static final Config INSTANCE = new Config();
}
public static Config getInstance() {
return .INSTANCE;
}
}
Singleton myths and gotchas β true or false?
EXERCISE 4/4A class with all static fields and static methods is the same as a Singleton.
The textbook lazy initialization (if instance == null then new ...) is thread-safe out of the box.
Bill Pugh's holder idiom requires no `synchronized` keyword to be thread-safe.
The Singleton pattern is just a fancy name for a global variable.
In Java, marking a Singleton as `Serializable` is enough to preserve its singleton-ness across serialization.
Eager Singleton wastes nothing β the instance is only "built" once anyway.
A Bill Pugh Singleton's Holder class is loaded when the outer class is loaded.