Build fluency in the vocabulary of a class deliberately allowing only one instance to ever exist.
0 / 5 completed
1 / 5
At standup, a dev mentions a class deliberately designed so only one instance of it can ever exist for the lifetime of the program, with every part of the code that asks for it receiving that exact same shared instance. What is this design pattern called?
The singleton pattern deliberately designs a class so only one instance of it can ever exist for the entire lifetime of the program, typically by making its constructor private and exposing a single access point that creates the instance the first time it's needed and returns that same instance on every later request. The factory pattern is a related but distinct pattern about creating new instances, often of varying types, rather than guaranteeing there's only ever one shared instance. This single-shared-instance guarantee is exactly what a singleton provides for something like a single configuration object or a single connection pool that genuinely should exist only once across the whole program.
2 / 5
During a design review, the team uses a singleton specifically for the application's central logging service, so every part of the codebase writes through the exact same shared logger instance rather than each creating its own separate one. Which capability does this shared-instance guarantee provide?
The singleton provides consistent, centralized logging behavior, since every part of the codebase writes through the exact same shared instance, guaranteeing they all share the same configuration, output destination, and formatting, rather than risking several separately created logger instances drifting apart with inconsistent settings. Letting every part of the codebase create and configure its own separate logger instance independently would risk exactly that kind of drift, where one part of the application logs differently from another for no good reason. This is exactly why a singleton is a natural fit for something genuinely central and shared, like a single application-wide logger.
3 / 5
In a code review, a dev notices a class is implemented as a singleton purely to make an object conveniently accessible from anywhere in the codebase, even though nothing about the underlying problem actually requires there to be only one instance. What does this represent?
This is a singleton misused as a global-access convenience, since reaching for the pattern purely to make an object easy to grab from anywhere, rather than because the underlying problem genuinely requires there to be exactly one instance, tends to introduce hidden coupling between unrelated parts of the codebase that all quietly depend on the same shared global state, and it makes substituting a different instance for testing significantly harder. A cache eviction policy is an unrelated concept about discarded cache entries. This convenience-only motivation is exactly why the singleton pattern has a reputation for being overused, since it's often reached for as a shortcut rather than because a real one-instance constraint actually exists.
4 / 5
An incident report shows a test suite became unreliable and tests started interfering with each other, because a class implemented as a singleton purely for convenient global access held mutable state that persisted across test runs, with no way to substitute a fresh instance for each individual test. What practice would prevent this?
Replacing the convenience-motivated singleton with regular dependency injection, explicitly passing an instance into whatever code needs it rather than reaching for one implicit global instance, lets each individual test supply its own fresh, isolated instance with no shared mutable state carrying over between runs, which is exactly the fix for the flaky-test incident described here. Continuing to rely on the shared singleton with no way to substitute a fresh instance per test is exactly what let one test's leftover state interfere with the next. This dependency-injection alternative is the standard fix whenever a singleton was adopted purely for access convenience rather than a genuine one-instance requirement.
5 / 5
During a PR review, a teammate asks why the team reserves the singleton pattern only for cases where a genuine one-instance requirement actually exists, instead of using it as a general-purpose convenience whenever an object needs to be reached from many different places in the codebase. What is the reasoning?
A singleton used purely for access convenience introduces hidden coupling between unrelated parts of the codebase that all quietly depend on the same implicit shared instance, and it makes substituting a different instance, such as a fake or a fresh one for an individual test, significantly harder, since the singleton's access pattern typically bypasses normal parameter passing entirely. A genuine one-instance requirement, like a hardware resource that can only meaningfully have one owner, actually justifies accepting those costs, but mere convenience of access does not, since regular dependency injection provides the same easy access without the coupling and testing downsides. The tradeoff is precisely this: the singleton pattern's real benefits only outweigh its real costs when the one-instance constraint reflects something true about the underlying problem, not just a shortcut for convenient reach.