Singleton

Ensure a class has only one instance

Overview

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. This is useful when exactly one object is needed to coordinate actions across the system.

Common use cases include database connections, logging, caching, thread pools, and configuration managers.

Key Concepts

Only one instance of the class exists

Global access point to that instance

Lazy or eager initialization

Thread-safe implementation options

Private constructor prevents external instantiation

Code Example

java
1// Thread-safe Singleton using Bill Pugh approach
2public class DatabaseConnection {
3    // Private constructor
4    private DatabaseConnection() {
5        System.out.println("Database connection established");
6    }
7    
8    // Static inner class - loaded only when getInstance() is called
9    private static class SingletonHelper {
10        private static final DatabaseConnection INSTANCE = new DatabaseConnection();
11    }
12    
13    public static DatabaseConnection getInstance() {
14        return SingletonHelper.INSTANCE;
15    }
16    
17    public void executeQuery(String query) {
18        System.out.println("Executing: " + query);
19    }
20}
21
22// Usage
23public class Main {
24    public static void main(String[] args) {
25        DatabaseConnection db1 = DatabaseConnection.getInstance();
26        DatabaseConnection db2 = DatabaseConnection.getInstance();
27        
28        System.out.println(db1 == db2); // true - same instance
29        
30        db1.executeQuery("SELECT * FROM users");
31    }
32}
33
34// Alternative: Double-Checked Locking (for lazy initialization)
35public class Logger {
36    private static volatile Logger instance;
37    
38    private Logger() {}
39    
40    public static Logger getInstance() {
41        if (instance == null) {
42            synchronized (Logger.class) {
43                if (instance == null) {
44                    instance = new Logger();
45                }
46            }
47        }
48        return instance;
49    }
50    
51    public void log(String message) {
52        System.out.println("[LOG] " + message);
53    }
54}
55
56// Modern approach: Enum Singleton (Joshua Bloch recommendation)
57public enum ConfigManager {
58    INSTANCE;
59    
60    private Properties config = new Properties();
61    
62    public void setProperty(String key, String value) {
63        config.setProperty(key, value);
64    }
65    
66    public String getProperty(String key) {
67        return config.getProperty(key);
68    }
69}

Three approaches: Bill Pugh (simple, thread-safe), Double-Checked Locking (lazy initialization), and Enum (simplest, serialization-safe).

When to Use

  • Database connection pools

  • Logger instances

  • Configuration managers

  • Cache implementations

  • Thread pools

  • Device drivers

Advantages

  • Controlled access to single instance

  • Reduced memory footprint

  • Global access point

  • Lazy initialization possible

  • Can be extended through subclassing

Disadvantages

  • Violates Single Responsibility Principle (manages its own creation)

  • Can make unit testing difficult

  • Hidden dependencies (global state)

  • May cause issues in multithreaded environments if not implemented correctly

  • Tight coupling to the singleton class

Real-World Example

  • Government: Only one president at a time
  • Sports: Only one captain in a team
  • Printer Spooler: Only one queue for all print jobs
  • File System: Only one instance manages disk access

Best Practices

  • 1.

    Use enum for simple singletons (prevents reflection and serialization issues)

  • 2.

    Ensure thread-safety in multithreaded applications

  • 3.

    Avoid using Singleton as a substitute for global variables

  • 4.

    Consider using Dependency Injection instead of Singleton

  • 5.

    Make the constructor private

  • 6.

    Don't create unnecessary singletons - use them only when truly needed

💡 Interview Tips

  • Explain different implementation approaches and their trade-offs

  • Discuss thread-safety concerns

  • Mention why enum is the best approach (per Joshua Bloch)

  • Be ready to write thread-safe code

  • Discuss anti-pattern concerns and alternatives like DI

  • Know how to break singleton (reflection, serialization, cloning)

AI Tutor

Ask about the topic

Sign in Required

Please sign in to use the AI tutor

Sign In
Singleton - Creational Patterns | LLD | Revise Algo