Singleton
The problem
Every part of the shop – checkout, search, shipping – needs the same configuration: currency, feature flags, the free-shipping threshold. Creating a config object in each place risks the copies drifting apart; passing one instance through every constructor by hand is exactly what you should do in a DI application, but plenty of code (CLIs, small services, libraries) has no container.
The pattern
One instance, globally reachable, created exactly once. The enum idiom is the recommended implementation in Java: the JVM guarantees single instantiation, thread safety, and safety against reflection and serialization attacks – for free.
if (ShopConfig.INSTANCE.isEnabled("gift-wrap")) { ... }
Benefits
- Guaranteed single instance – no double-checked-locking subtleties; the class loader does the hard work.
- Shared state stays consistent – everyone reads the same flags and thresholds.
- Lazy enough – the instance is created on first use of the enum class.
The honest caveat
Singletons are shared mutable global state: they hide dependencies (nothing in a method signature
says it reads config) and they leak state between tests – note the reset() hook the test needs.
In an application with a DI container, prefer a normal class registered as a singleton-scoped
bean: same one-instance benefit, but injected, visible in constructors, and swappable in tests.
The pattern is still worth knowing because you constantly meet it: Runtime.getRuntime(),
loggers, driver registries.
Seen in the wild
Runtime.getRuntime(), Desktop.getDesktop(), SLF4J LoggerFactory’s internal state, Spring’s
default bean scope (conceptually).
Implementation
ShopConfig – the enum-idiom singleton.