Singleton Pattern
Java Singleton Pattern (CREATIONAL PATTERN)
Ensures only one instance of a class exists and provides global access to it.
Singleton Pattern: Ensures one instance of a class exists with global access - use Bill Pugh or Enum implementation for thread safety.
2. When to Use?
Section titled “2. When to Use?”When you need:
- Single point of control (Logger, Config, Cache)
- Shared resource (Database connection)
- Global access point
- Expensive object to create (create once, reuse)
3. Simple Example: Basic Singleton
Section titled “3. Simple Example: Basic Singleton”❌ Problem Without Singleton
Section titled “❌ Problem Without Singleton”class DatabaseConnection { // Multiple instances can be created}
// Different parts of code create separate instancesDatabaseConnection conn1 = new DatabaseConnection();DatabaseConnection conn2 = new DatabaseConnection();// conn1 != conn2 - Multiple connections!✅ Basic Singleton Implementation
Section titled “✅ Basic Singleton Implementation”public class DatabaseConnection { // 1. Private static instance private static DatabaseConnection instance;
// 2. Private constructor - prevents external instantiation private DatabaseConnection() { System.out.println("Database connection created"); }
// 3. Public static method to get instance public static DatabaseConnection getInstance() { if (instance == null) { instance = new DatabaseConnection(); // Lazy initialization } return instance; }
public void connect() { System.out.println("Connected to database"); }}
// Usagepublic class Main { public static void main(String[] args) { // Always get the same instance DatabaseConnection conn1 = DatabaseConnection.getInstance(); DatabaseConnection conn2 = DatabaseConnection.getInstance();
System.out.println(conn1 == conn2); // true - Same object! conn1.connect(); }}4. Singleton Variations
Section titled “4. Singleton Variations”1. Eager Initialization (Thread-safe)
Section titled “1. Eager Initialization (Thread-safe)”public class EagerSingleton { // Create instance when class loads private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() { return instance; // Always returns pre-created instance }}2. Lazy Initialization with Double-Check Locking (Thread-safe & Efficient)
Section titled “2. Lazy Initialization with Double-Check Locking (Thread-safe & Efficient)”public class ThreadSafeSingleton { // volatile ensures visibility across threads private static volatile ThreadSafeSingleton instance;
private ThreadSafeSingleton() {}
public static ThreadSafeSingleton getInstance() { if (instance == null) { // First check (no locking) synchronized (ThreadSafeSingleton.class) { if (instance == null) { // Second check (with locking) instance = new ThreadSafeSingleton(); } } } return instance; }}3. Bill Pugh Singleton (Best - Thread-safe & Efficient)
Section titled “3. Bill Pugh Singleton (Best - Thread-safe & Efficient)”public class BillPughSingleton { private BillPughSingleton() {}
// Static inner class - loaded only when getInstance() is called private static class SingletonHelper { private static final BillPughSingleton INSTANCE = new BillPughSingleton(); }
public static BillPughSingleton getInstance() { return SingletonHelper.INSTANCE; // Thread-safe by JVM design }}4. Enum Singleton (Recommended by Joshua Bloch)
Section titled “4. Enum Singleton (Recommended by Joshua Bloch)”public enum EnumSingleton { INSTANCE; // Single instance guaranteed by JVM
// Add methods public void doSomething() { System.out.println("Singleton method"); }}
// UsageEnumSingleton.INSTANCE.doSomething();5. Real-World Examples
Section titled “5. Real-World Examples”Example 1: Logger Singleton
Section titled “Example 1: Logger Singleton”public class Logger { private static Logger instance; private List<String> logs = new ArrayList<>();
private Logger() {} // Private constructor
public static Logger getInstance() { if (instance == null) { instance = new Logger(); } return instance; }
public void log(String message) { logs.add(message); System.out.println("LOG: " + message); }
public List<String> getLogs() { return new ArrayList<>(logs); // Return copy }}
// Usage anywhere in applicationLogger.getInstance().log("User logged in");Logger.getInstance().log("File uploaded");Example 2: Configuration Manager
Section titled “Example 2: Configuration Manager”public class ConfigManager { private static ConfigManager instance; private Properties config = new Properties();
private ConfigManager() { // Load configuration once loadConfig(); }
public static ConfigManager getInstance() { if (instance == null) { synchronized (ConfigManager.class) { if (instance == null) { instance = new ConfigManager(); } } } return instance; }
private void loadConfig() { // Load from file/database config.setProperty("db.url", "localhost:3306"); config.setProperty("app.name", "MyApp"); }
public String getProperty(String key) { return config.getProperty(key); }}
// UsageString dbUrl = ConfigManager.getInstance().getProperty("db.url");6. Interview Q&A
Section titled “6. Interview Q&A”Q1: Why is basic singleton not thread-safe?
Section titled “Q1: Why is basic singleton not thread-safe?”A: Two threads can both pass if (instance == null) check and create separate instances. Use double-check locking or Bill Pugh method.
Q2: Which singleton implementation is best?
Section titled “Q2: Which singleton implementation is best?”A:
- Bill Pugh: Clean, thread-safe, efficient (no synchronization)
- Enum: Simplest, thread-safe, serialization-safe
- Double-check locking: Efficient for multi-threaded
Q3: How to prevent Singleton from cloning?
Section titled “Q3: How to prevent Singleton from cloning?”A: Override clone() method:
@Overrideprotected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException();}Q4: How to prevent Singleton from serialization?
Section titled “Q4: How to prevent Singleton from serialization?”A: Implement readResolve() method:
protected Object readResolve() { return getInstance(); // Return existing instance}Q5: Singleton vs Static Class?
Section titled “Q5: Singleton vs Static Class?”A:
| Singleton | Static Class |
|---|---|
| Can implement interfaces | Cannot implement interfaces |
| Can be passed as parameter | Cannot be passed |
| Can inherit from other classes | Cannot inherit |
| Lazy initialization possible | Eager initialization only |
| Can have state | Stateless |
Q6: Real Singleton in JDK?
Section titled “Q6: Real Singleton in JDK?”A:
Runtime.getRuntime()- SingletonDesktop.getDesktop()- SingletonSystem.getSecurityManager()- Singleton
7. Common Pitfalls & Solutions
Section titled “7. Common Pitfalls & Solutions”1. Reflection Attack Prevention
Section titled “1. Reflection Attack Prevention”public class ReflectionSafeSingleton { private static ReflectionSafeSingleton instance; private static boolean created = false;
private ReflectionSafeSingleton() { if (created) { throw new RuntimeException("Use getInstance() method"); } created = true; }
public static ReflectionSafeSingleton getInstance() { if (instance == null) { instance = new ReflectionSafeSingleton(); } return instance; }}2. Serializable Singleton
Section titled “2. Serializable Singleton”public class SerializableSingleton implements Serializable { private static final long serialVersionUID = 1L;
private static SerializableSingleton instance = new SerializableSingleton();
private SerializableSingleton() {}
public static SerializableSingleton getInstance() { return instance; }
// This method preserves singleton during deserialization protected Object readResolve() { return getInstance(); }}8. Spring Framework & Singleton
Section titled “8. Spring Framework & Singleton”// Spring beans are singletons by default@Component // Spring manages as singletonpublic class UserService { // All injections get same instance}
// Different scopes available@Scope("singleton") // Default - one per container@Scope("prototype") // New instance each time@Scope("request") // One per HTTP request@Scope("session") // One per HTTP session9. Implementation Template
Section titled “9. Implementation Template”// Best Practice: Bill Pugh Singletonpublic class MySingleton { // 1. Private constructor private MySingleton() { // Initialization code }
// 2. Static inner class private static class SingletonHolder { private static final MySingleton INSTANCE = new MySingleton(); }
// 3. Public access method public static MySingleton getInstance() { return SingletonHolder.INSTANCE; }
// 4. Business methods public void businessMethod() { // Your logic }}10. When NOT to Use Singleton
Section titled “10. When NOT to Use Singleton”- Testing: Hard to mock
- Global state: Can lead to hidden dependencies
- Concurrency issues: If not properly implemented
- Memory leaks: Singleton holds references
- Flexibility: Can’t extend or change behavior easily