Design Patterns interview question · Most asked

How do you implement a Singleton, and why is it often considered an anti-pattern?

Summary

A Singleton has a private constructor and a static accessor that creates the single instance on first use and returns it afterwards. It's criticised because its global access hides dependencies, shares mutable state across tests and requests, and makes swapping implementations hard.

Longer Answer

The "exactly one instance" guarantee is sometimes useful (a connection pool, a hardware interface), but the global access point is the problem: any code can reach it, tests leak state into each other, and parallel code needs thread safety (in Java: a synchronized accessor, the holder idiom, or an enum).

The usual alternative: create one instance at startup and inject it, or register it with singleton scope in a DI container (Spring's default scope, Laravel's singleton()). In Python, a module-level object is the idiomatic singleton.

Code Example

class Config:
    _instance = None

    @classmethod
    def instance(cls):
        if cls._instance is None:  # created lazily, on first use
            cls._instance = cls()
        return cls._instance


print("same object:", Config.instance() is Config.instance())

Key Points

  • Private constructor + static accessor.
  • Global access hides dependencies and leaks state.
  • Thread-safe lazy init in Java: holder idiom or enum.
  • Prefer one injected instance or container singleton scope.

Deep dive: Design Patterns, Explained Simply: Singleton

Explanation

What interviewers look for

A correct implementation (thread safety in Java), the testing/global-state critique, and the injected-instance alternative.

Follow-up questions

  • How would you test code that uses a singleton?
  • What does Spring's singleton scope mean?

More most-asked Design Patterns questions

← All Design Patterns questions