Skip to content

Design Patterns

🏗️ Design Patterns

Have you worked on any design patterns?

Yes, I have primarily worked with creational design patterns like Singleton and Factory. These patterns help in controlling object creation and improving code maintainability. In real-world applications, I have used Singleton for shared resources such as configuration management, logging, and database connections.


How does Singleton design pattern work?

The Singleton design pattern ensures that only one instance of a class exists throughout the application and provides a global access point to that instance.

Key Characteristics:

  • The constructor is private to prevent external instantiation
  • A static variable holds the single instance
  • A public static method provides access to the instance

Basic Implementation (Lazy Initialization):

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

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

### Problem:

This implementation is not thread-safe. In a multithreaded environment, multiple threads can create multiple instances
simultaneously.

---

## Singleton in multithreading?

To make Singleton thread-safe, we need to handle concurrent access.

### Approach 1: Synchronized Method

```java
public static synchronized Singleton getInstance()
  • Ensures thread safety
  • But reduces performance because every call acquires a lock

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) { // First check
            synchronized (Singleton.class) {
                if (instance == null) { // Second check
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Why double check?

  • First check avoids unnecessary locking
  • Second check ensures only one instance is created

Why use volatile?

Without volatile, JVM may reorder instructions:

  1. Allocate memory
  2. Assign reference
  3. Initialize object

This can result in another thread accessing a partially constructed object.

Interview Tip:

Double-checked locking improves performance while maintaining thread safety.


Can Singleton be serialized?

Yes, a Singleton class can be serialized, but serialization can break the Singleton pattern.


What is serialization?

Serialization is the process of converting an object into a byte stream so that it can be:

  • Stored in a file
  • Sent over a network
  • Cached for later use

Deserialization is the reverse process where the byte stream is converted back into an object.


How does serialization/deserialization break Singleton?

During deserialization, Java creates a new object instead of returning the existing instance.

Example:

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file.ser"));
Singleton obj2 = (Singleton) ois.readObject();

Now:

  • obj1 → original instance
  • obj2 → new instance

This violates the Singleton principle.


How to fix it?

Solution: Implement readResolve()

protected Object readResolve() {
    return instance;
}

How it works:

  • During deserialization, JVM calls readResolve()
  • Instead of returning the newly created object, it returns the existing Singleton instance

Additional Best Practice (Bill Pugh Singleton)

This is a cleaner and thread-safe approach:

public class Singleton {

    private Singleton() {
    }

    private static class Helper {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Helper.INSTANCE;
    }
}

Advantages:

  • Thread-safe without synchronization
  • Lazy loading
  • Better performance

Another Alternative: Enum Singleton (Safest)

public enum Singleton {
    INSTANCE;
}

Advantages:

  • Automatically thread-safe
  • Handles serialization internally
  • Protects against reflection attacks

Common Interview Follow-ups

1. Can Singleton be broken using reflection?

Yes. Reflection can access the private constructor and create multiple instances.

Fix:

Add a check inside constructor:

if (instance != null) {
    throw new RuntimeException("Use getInstance()");
}

2. Where is Singleton used in real projects?

  • Logging frameworks
  • Configuration managers
  • Database connection pools
  • Caching systems

3. When should you avoid Singleton?

  • When unit testing is required (tight coupling)
  • When state changes frequently
  • When scalability is needed

Final Summary

  • Singleton ensures a single instance
  • Must handle:

    • Multithreading
    • Serialization
    • Reflection
    • Best implementations:

    • Double-checked locking

    • Bill Pugh method
    • Enum Singleton