Singleton Pattern

One instance of a class, reached from one place. Know how to build it safely, why interviewers treat it as a smell, and what to use instead.

Overview

The Singleton is one of the five creational patterns in the Gang of Four book (Gamma, Helm, Johnson and Vlissides, *Design Patterns*, 1994). Its job is small: make sure a class has exactly one instance, and give the whole program one way to reach it.

The classic build has three parts. The constructor is private, so nobody else can call it. A static field holds the one instance. A static accessor, usually called getInstance(), creates the instance the first time and returns the same object after that.

Interviewers ask about Singleton for two reasons. First, the thread-safety details show whether you understand initialization and memory ordering. Second, the pattern is widely criticized, and a strong answer names the costs (global state, hidden dependencies, hard tests) and offers the modern alternative: create one instance and inject it.

A Python Singleton that runs

Python has no private constructors, so the usual place to enforce one instance is new, the method that creates the object before init runs. The lock makes the first creation safe when several threads call Config() at once; the outer None check keeps later calls cheap.

The state is set up inside new on purpose. Python calls init every time new returns an instance of the class, so an init that reset values would wipe the shared state on every Config() call. The last key question shows that trap.

Six ways to get one instance

Each language gives you a different guarantee to lean on. The table is the part of the answer interviewers listen for: not the code, but why each version is safe.

  • Eager static field — Java — The JVM initializes a class once, under a lock (JLS 12.4.2) — Created when the class is initialized, even if getInstance() is never called
  • Holder class — Java — A nested class is initialized on first use of its static field (JLS 12.4.1), once (12.4.2) — None; lazy and lock-free
  • Double-checked locking — Java — A write to a volatile field happens-before every later read of it (JLS 17.4.5) — Easy to get wrong without volatile
  • Enum with one constant — Java — The constant is a static field of the enum class, so it is created once, when that class is initialized (JLS 12.4.2) — Cannot extend a class
  • Lock in the accessor — Python — A mutex around the check-and-create — One lock per call, or double-check
  • Module-level object — Python — A module runs once per interpreter and is cached in sys.modules — Not a class; harder to reset in tests

Why interviewers push back

A Singleton is a global variable with a class around it. The cost shows up the moment you write a test.

  • Global state — Any code anywhere can change it; bugs depend on call order
  • Hidden dependency — The class that uses it does not declare it, so readers and tests cannot see it
  • Hard to test — Tests share one instance, so one test's changes leak into the next
  • Two jobs in one class — The class does its real work and also manages its own lifetime
  • Shared mutable state — Every mutating method now needs its own synchronization

The modern answer is to keep the 'one instance' but drop the 'global access'. Create the object once at startup, in main or a dependency-injection container, and pass it to the classes that need it. Tests pass a fake instead.

Where you meet it for real

  • Python logging.getLogger(name) — Every call with the same name returns the same logger; with no name, the root logger. A registry of named instances, not one global
  • A Python module — Imported once, then served from sys.modules; module-level objects are shared by every importer
  • A DI container's singleton scope — The container creates one instance per application and injects it; the class itself stays an ordinary class

What you will be able to do

  • Write a thread-safe Singleton in Python and Java and say why each version is safe.
  • Name the costs of the pattern in one breath: global state, hidden dependency, hard tests.
  • Refactor a Singleton call into an injected dependency and show the test that becomes possible.
  • Tell an interviewer when one instance is a real requirement and when it is only convenience.

Interview questions

  • How do you make a Singleton thread-safe in Java?
  • Why is Singleton often called an anti-pattern, and how would you fix code that uses one?
  • When is a Singleton the right choice?
  • What is the difference between a Singleton, a class with only static methods, and a DI-scoped singleton?
  • What goes wrong with the new approach in Python, and what are the alternatives?

Sign up free to read the full topic

More Low-Level Design topics

Start free on Cariara · Coding problems · System design studio