$ emrebener

Singleton Pattern

author: emre bener read time: 3 min about: singleton pattern, java repository: https://github.com/Emrebener/GoF-Design-Patterns-Creational
published: updated: mentions: software design pattern, creational pattern, enumerated type, effective java, garbage collection

1. What singleton is

A singleton is a class that hands out exactly one instance of itself, for the lifetime of the program, through a single global access point. The Gang of Four put it in the creational bucket because it’s about who controls construction: the class itself, not its callers.

The usual reason to reach for the pattern is a resource that doesn’t make sense to duplicate. A configuration registry loaded once at startup, a connection pool, a logger that funnels into a single sink.

One instance, accessed from anywhere, never reconstructed/recreated.

That’s the whole pattern. The interesting part is how Java lets you write one without tripping over the language’s own sharp edges.

2. Writing one in Java

2.1. The eager static field

The simplest singleton in Java is a class with a private constructor and a single public static final instance:

public final class Config {
    public static final Config INSTANCE = new Config();

    private Config() {
        // load settings, etc.
    }

    public String get(String key) { /* ... */ }
}

Callers reach it through Config.INSTANCE. The constructor is private, so nobody outside the class can call new Config(). The JVM constructs the instance the first time the class is loaded, and never again.

This works. It’s eager: the instance gets built whether you use it or not, but for most singletons that’s fine. Configuration, loggers and pools want to be ready before the first caller asks.

There’s a catch though. This version isn’t entirely bulletproof. Reflection can call the private constructor anyway, and serialization can produce a second instance on deserialization. Neither really matters in a disciplined codebase, but if you want a singleton that genuinely cannot be duplicated, there’s a better option.

2.2. The enum singleton

Joshua Bloch’s recommendation in Effective Java is to use a single-element enum:

public enum Config {
    INSTANCE;

    public String get(String key) { /* ... */ }
}

That’s the whole declaration. Callers still write Config.INSTANCE.get(...). The JVM guarantees exactly one instance per enum constant, and the language refuses to let reflection or serialization create a second one. Same ergonomics as the static-field version, loopholes closed.

The only real downside: you can’t extend a class, because enums implicitly extend java.lang.Enum. If your singleton needs to inherit from something, fall back to the static-field version. Otherwise, this is the one to use.

3. When not to use it

Singleton has a bad reputation, and it’s not for no reason. The pattern itself is fine. The trouble is that “I only need one of these” is a much weaker reason to make something a singleton than people assume. A few things to consider before reaching for it:

  • It’s global state in a costume. A singleton accessed from anywhere is a global variable in all but name, with the usual downsides: callers depend on it implicitly, you can’t tell from a method signature what it touches, and changing its behaviour ripples in ways you can’t anticipate.
  • It fights tests. A singleton’s whole point is that there’s exactly one of it, forever. Tests want the opposite: fresh state per test, swapped fakes, controlled lifecycle. You can end up using reflection just to get tests to run, which is a smell on its own.
  • It’s a memory-leak magnet. A singleton lives for the lifetime of the JVM, and so does anything it holds a reference to. Register a listener with a singleton event bus and forget to unregister, cache request-scoped objects in a singleton map, hand a singleton service a reference to a short-lived component, and none of those will ever be garbage collected. The longer-lived object always wins, and a singleton is the longest-lived object there is. Just because you’re working in a high-level language doesn’t mean you’re safe from memory leaks :)

Rule of thumb: if you’re reaching for a singleton because it’s convenient, you probably want a regular object you construct once at the top of main and thread through. If you’re reaching for it because the thing itself must be unique at the JVM level, that’s when the pattern earns its keep.