Singleton Pattern

1. What is Singleton?

The Singleton Design Pattern means:

A class is allowed to create only one object during the entire lifetime of the application, and that same object is reused everywhere.

So instead of:

  • Creating a new object every time

We:

  • Create one object once
  • Share it across the application

Think of it like:

  • One central authority
  • Everyone refers to the same source

2. Why Do We Need Singleton?

To understand why, first understand the problem.

Without Singleton (Problem)

In a large application (like a bank):

  • Multiple services run at the same time
  • Each service may create its own object
  • Some objects are not meant to be duplicated

This leads to:

  • Wasted memory
  • Inconsistent data
  • Unexpected behavior
  • Performance issues

3. Example: Bank Configuration

A bank has:

  • Interest rates
  • Daily transaction limits
  • Feature flags (enabled / disabled services)

These values:

  • Are same for everyone
  • Should be loaded once
  • Should not change randomly

If every service loads its own configuration:

  • One service may use old values
  • Another may use new values

This causes business inconsistency.

πŸ‘‰ Singleton ensures one shared configuration object


4. Core Idea Behind Singleton (How It Works)

Singleton is based on three simple rules:

  1. No one should create the object directly
  2. Only the class itself creates the object
  3. Everyone accesses the same object

This is achieved by:

  • Making the constructor private
  • Storing the object in a static variable
  • Providing a static method to access it

5. Simple Example (Easy to Understand)

public class BankConfig {

    private static BankConfig instance;

    private BankConfig() {
        // private constructor
    }

    public static BankConfig getInstance() {
        if (instance == null) {
            instance = new BankConfig();
        }
        return instance;
    }
}

What is happening here?

  • private constructor β†’ prevents new BankConfig()

  • static instance β†’ shared across application

  • getInstance() β†’ controls object creation


6. Why This Simple Version Is NOT Enough

In real systems:

  • Many threads run in parallel

  • Two threads may enter getInstance() at the same time

  • Both may create objects

This breaks the only one instance rule ⚠️ Especially dangerous in banking systems


7. Thread-Safe Singleton (Real-World Ready)

public class BankConfig {

    private static volatile BankConfig instance;

    private BankConfig() {}

    public static BankConfig getInstance() {
        if (instance == null) {
            synchronized (BankConfig.class) {
                if (instance == null) {
                    instance = new BankConfig();
                }
            }
        }
        return instance;
    }
}
  • synchronized β†’ only one thread enters at a time

  • double check β†’ avoids unnecessary locking

  • volatile β†’ ensures all threads see the same object

This version:

  • Is safe

  • Is efficient


8. Best and Cleanest Singleton in Java (Enum)

public enum BankAuditLogger {
    INSTANCE;

    public void log(String message) {
        System.out.println("AUDIT: " + message);
    }
}

Enum = Singleton ONLY if it has exactly ONE enum constant

❌ NOT Singleton

public enum BankRole {
    ADMIN,
    CASHIER,
    MANAGER
}

Why Enum Singleton is Preferred

  • Java guarantees only one enum instance

  • Thread-safe by default

  • Safe from reflection & serialization issues

  • Very little code

πŸ‘‰ Many senior developers prefer this approach


9. Singleton in Spring Boot

In Spring Boot:

@Service
public class TransactionService {
}

By default:

  • Spring creates only one instance

  • Manages lifecycle for you

So:

  • You rarely write Singleton manually

  • You rely on Dependency Injection

πŸ‘‰ Singleton pattern is still important to understand, not always to implement


10. Alternatives to Singleton (Modern Approach)

Dependency Injection (Preferred)

Instead of:

BankConfig.getInstance();

We use:

@Autowired
private BankConfig bankConfig;

Why this is better:

  • Easy to test

  • Loose coupling

  • Cleaner design


11. When NOT to Use Singleton

Avoid Singleton when:

  • Object holds user-specific data

  • Multiple configurations are required

  • Unit testing becomes hard

  • Global state causes hidden bugs

Singleton is powerful, but dangerous if misused.


12. Summary

  • Singleton controls object creation

  • Thread safety depends on implementation

  • Enum Singleton is safest

  • Spring beans are singleton by default

  • Overuse of Singleton is considered a design smell

Singleton ensures a single shared instance, but in modern Spring applications, dependency injection is preferred over manual Singleton implementation.


This site uses Just the Docs, a documentation theme for Jekyll.