Design Pattern

Singleton Pattern

Clean Java-only production-ready implementation.


Ensure a class has exactly ONE instance and provide a global point of access.

1. Eager Initialization (Simple, Safe)

Static initialization creates the instance immediately during class loading. It is simple, thread-safe, and perfect if the instance is cheap or always used. To be absolutely resilient against reflection/serialization attacks out of the box, use an **Enum Singleton**.

2. Lazy Initialization (Thread-Safe)

Use when initialization is expensive (reads from disk, connects to DB) and you may not always need it. For senior/production-ready applications, the implementation must prevent **Reflection attacks**, **Serialization bypasses**, and **Cloning bypasses**, while securing thread-safety via **Double-Checked Locking (DCL)** with a volatile field, or the static **Bill Pugh Holder Idiom**.

// ─── DOUBLE-CHECKED LOCKING SINGLETON (SENIOR PATTERN) ──────────────────────
// Thread-safe, high-performance, and resilient against typical bypass vectors:
// 1. Reflection Attacks (guards in constructor)
// 2. Serialization Attacks (defines readResolve())
// 3. Cloning Attacks (overrides clone())
// ────────────────────────────────────────────────────────────────────────────
import java.io.Serializable;

final class DatabaseConnectionPool implements Serializable, Cloneable {
    private static final long serialVersionUID = 1L;
    
    // volatile is CRITICAL: prevents instruction reordering.
    // Without volatile, a thread may observe a non-null, uninitialized reference:
    // Memory Allocated -> Assigned to Reference -> Constructor Executes (Reordered!)
    private static volatile DatabaseConnectionPool instance;

    private DatabaseConnectionPool() {
        // Reflection defense: prevent instantiation via Constructor.newInstance()
        if (instance != null) {
            throw new IllegalStateException("Instance already initialized. Use getInstance().");
        }
        System.out.println("  [DatabaseConnectionPool] Expensive resource initialization...");
    }

    public static DatabaseConnectionPool getInstance() {
        DatabaseConnectionPool localRef = instance; // Use local variable for 25% performance boost
        if (localRef == null) {
            synchronized (DatabaseConnectionPool.class) {
                localRef = instance;
                if (localRef == null) {
                    instance = localRef = new DatabaseConnectionPool();
                }
            }
        }
        return localRef;
    }

    // Serialization defense: returns the existing instance during deserialization
    protected Object readResolve() {
        return getInstance();
    }

    // Cloning defense: prevent cloning
    @Override
    protected Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException("Singleton cloning is prohibited.");
    }
}

public class Main {
    public static void main(String[] args) {
        DatabaseConnectionPool pool1 = DatabaseConnectionPool.getInstance();
        DatabaseConnectionPool pool2 = DatabaseConnectionPool.getInstance();
        
        System.out.println("  [Main] Same instance? " + (pool1 == pool2)); // Should output: true
    }
}