The Singleton pattern ensures a class has only one instance and provides a global access point to it.

Problem

Some classes should have exactly one instance — configuration managers, connection pools, loggers.

Solution

  public class DatabaseConfig {
    private static volatile DatabaseConfig instance;

    private DatabaseConfig() {
        // private constructor prevents instantiation
    }

    public static DatabaseConfig getInstance() {
        if (instance == null) {
            synchronized (DatabaseConfig.class) {
                if (instance == null) {
                    instance = new DatabaseConfig();
                }
            }
        }
        return instance;
    }
}
  

The simplest and thread-safe approach:

  public enum DatabaseConfig {
    INSTANCE;

    private String url = "jdbc:postgresql://localhost/mydb";

    public String getUrl() { return url; }
    public void setUrl(String url) { this.url = url; }
}

// Usage
DatabaseConfig.INSTANCE.getUrl();
  

Guaranteed single instance by JVM, serialization-safe, and reflection-safe.

Static Holder Pattern

Lazy initialization without synchronization overhead:

  public class DatabaseConfig {
    private DatabaseConfig() { }

    private static class Holder {
        static final DatabaseConfig INSTANCE = new DatabaseConfig();
    }

    public static DatabaseConfig getInstance() {
        return Holder.INSTANCE;
    }
}
  

When to Use

  • Exactly one instance is required
  • Global access point is needed
  • Lazy initialization is desired

Java Examples

  • Runtime.getRuntime()
  • Collections.emptyList() and other factory singletons
  • Spring beans with @Scope("singleton") (default)

Best Practices

  • Prefer enum singleton for simplicity and safety
  • Avoid singletons for testability — consider dependency injection instead
  • Do not use singleton as a global mutable state container
  • In Spring applications, use the IoC container instead of manual singletons