DEV Community

Cover image for Mastering the Singleton Design Pattern in Java – A Complete Guide
ZeeshanAli-0704
ZeeshanAli-0704

Posted on • Edited on

Mastering the Singleton Design Pattern in Java – A Complete Guide

πŸ“š Table of Contents

  1. What is Singleton Design Pattern?
  2. Why Use Singleton?
  3. Requirements of a Singleton Class
  4. Implementation Types
  5. Thread Safety in Singleton
  6. Real World Use Cases
  7. Comparison Table
  8. Advantages
  9. Disadvantages
  10. Notes & Best Practices
  11. Quick Test
  12. Conclusion

Part 2 - Why You Should Avoid Singleton Pattern in Modern Java Projects

🎯 Singleton Design Pattern in Java

β€œEnsure a class has only one instance and provide a global point of access to it.”


πŸ” 1. What is Singleton Design Pattern?

The Singleton Pattern is a creational design pattern that ensures a class is instantiated only once during the application's lifecycle and provides global access to that instance.


πŸ“Œ 2. Why Use Singleton?

  • πŸ”„ Consistency: All parts of the application use the same instance.
  • πŸ’Ύ Memory Efficient: Avoids creating multiple objects.
  • πŸ” Control Access: Especially for shared resources like databases, loggers, caches, etc.

🧱 3. Basic Requirements of a Singleton Class

  1. Private Constructor: Prevents instantiation from outside the class.
  2. Static Reference: Holds the single instance of the class.
  3. Public Static Method: Returns the singleton instance.

βš™οΈ 4. Implementation Types

βœ… A Eager Initialization

The instance is created when the class is loaded (whether you use it or not).

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… Advantages

  • Thread-safe by default (because of class loading).
  • Simple to implement.

❌ Disadvantages

  • Instance is created even if not used.
  • Not ideal when object creation is resource-heavy.

βœ… B Lazy Initialization

The instance is created only when needed.

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ… Advantages

  • Saves memory if instance is never needed.

❌ Disadvantages

  • Not thread-safe. In a multithreaded environment, two threads may create different instances.

🧡 5. Thread Safety in Singleton

🚫 Problem:

Two threads might simultaneously enter the getInstance() method and create multiple instances β€” breaking the singleton guarantee.

πŸ”’ Solutions:


βœ… A Synchronized Method

public class ThreadSafeSingleton {
    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton() {}

    public static synchronized ThreadSafeSingleton getInstance() {
        if (instance == null) {
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • βœ… Thread-safe
  • ❌ Slower performance due to method-level lock

βœ… B Double Checked Locking

public class DoubleCheckedSingleton {
    private static volatile DoubleCheckedSingleton instance;

    private DoubleCheckedSingleton() {}

    public static DoubleCheckedSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedSingleton();
                }
            }
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • βœ… Lazy loaded
  • βœ… Thread-safe
  • βœ… High performance
  • πŸ”’ Requires volatile to prevent instruction reordering

βœ… 6. Real World Use Cases

Use Case Why Singleton?
JDBC Connection Single DB connection manager to avoid new creation
Logger Utility Central logging system for the entire application
Configuration Global configuration manager instance
Cache Manager Central cache layer shared across app modules
File System Access to shared file resources

πŸ“Š 7. Comparison Table

Approach Lazy? Thread-Safe? Performance Use Case
Eager Initialization ❌ βœ… Fast Lightweight obj
Lazy Initialization βœ… ❌ Poor (MT) Simple apps
Synchronized Method βœ… βœ… Slow Small-scale apps
Double-Checked Locking βœ… βœ… Good Web/Server apps

βœ… 8. Advantages of Singleton Pattern

πŸ‘ Pros
Ensures a single instance across app lifecycle
Saves memory by preventing redundant object creation
Globally accessible instance (controlled access)
Great for shared resources (DB, Logger, Configs)

❌ 9. Disadvantages of Singleton Pattern

πŸ‘Ž Cons
Difficult to test (mocking is tricky)
Introduces global state (violates OOP encapsulation)
Hidden dependencies across classes
Thread safety can be hard to ensure (if not properly done)

πŸ“ 10. Notes & Best Practices

  • Always prefer Bill Pugh Singleton or Enum Singleton for thread safety & performance.
  • Avoid excessive global access. Use dependency injection where possible.
  • Singleton is an anti-pattern in some contexts (because it can hide dependencies).
  • Use volatile with double-checked locking to ensure visibility across threads.
  • Prefer stateless singletons to avoid concurrency issues.

πŸ§ͺ 11. Quick Test

public class SingletonTest {
    public static void main(String[] args) {
        Runnable task = () -> {
            DoubleCheckedSingleton obj = DoubleCheckedSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + ": " + obj.hashCode());
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start(); t2.start();
    }
}
Enter fullscreen mode Exit fullscreen mode

You should see the same hashCode from both threads.


βœ… Conclusion

The Singleton Pattern is simple, powerful, and commonly used, but requires careful handling in multithreaded environments. If you're designing a service or resource that should only exist once, Singleton is your go-to pattern β€” just be mindful of its drawbacks and test carefully.


πŸ“š Explore More Design Patterns in Java


More Details:

Get all articles related to system design
Hastag: SystemDesignWithZeeshanAli

systemdesignwithzeeshanali

Git: https://github.com/ZeeshanAli-0704/SystemDesignWithZeeshanAli

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.