Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Singleton Pattern

Overview

The Singleton Pattern ensures a class has only one instance and provides a global point of access to it.

Pattern Structure

The Singleton Pattern restricts instantiation of a class to a single object by:

  • Making the constructor private
  • Providing a static method that returns the single instance
  • Storing the instance in a static variable

Key Concepts

  • Private Constructor: Prevents external instantiation
  • Static Instance: Holds the one and only instance
  • Static Access Method: getInstance() provides global access to the instance
  • Lazy Initialization: Instance is created only when first requested (in some implementations)

Examples

SimpleSingleton

Basic implementation of the Singleton pattern with lazy initialization.

Note: This implementation is NOT thread-safe. In a multithreaded environment, multiple instances could be created.

Multithreading

Demonstrates various thread-safe implementations of the Singleton pattern:

Thread-Safe Implementations

1. Synchronized Method

public static synchronized Singleton getInstance() {
    if (uniqueInstance == null) {
        uniqueInstance = new Singleton();
    }
    return uniqueInstance;
}
  • Pros: Simple, thread-safe
  • Cons: Synchronization overhead on every call (only needed on first call)

2. Eager Initialization

private static Singleton uniqueInstance = new Singleton();

public static Singleton getInstance() {
    return uniqueInstance;
}
  • Pros: Simple, thread-safe, no synchronization overhead
  • Cons: Instance created even if never used, no lazy initialization

3. Double-Checked Locking

private volatile static Singleton uniqueInstance;

public static Singleton getInstance() {
    if (uniqueInstance == null) {
        synchronized (Singleton.class) {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
        }
    }
    return uniqueInstance;
}
  • Pros: Thread-safe, minimal synchronization overhead, lazy initialization
  • Cons: More complex, requires volatile keyword (Java 5+)

4. Bill Pugh Singleton (Recommended)

private Singleton() {}

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

public static Singleton getInstance() {
    return SingletonHelper.INSTANCE;
}
  • Pros: Thread-safe, lazy initialization, no synchronization, simple
  • Cons: None (this is the recommended approach)

How to Compile

From the parent directory of Singleton:

javac -d out Singleton/SimpleSingleton/*.java
javac -d out Singleton/Multithreading/*.java

How to Run

These classes are pattern implementations without a main method and cannot be run directly. They are intended to be used as library classes in a larger application.

Benefits of the Singleton Pattern

  • Controlled Access: Ensures only one instance exists
  • Reduced Namespace Pollution: Better than global variables
  • Permits Refinement: Can subclass singleton (though not common)
  • Lazy Initialization: Can defer creation until needed (some implementations)
  • Global Access: Accessible from anywhere in the application

Drawbacks of the Singleton Pattern

  • Global State: Can make code harder to test and maintain
  • Hidden Dependencies: Dependencies on singleton are not obvious
  • Difficult to Test: Hard to mock or replace in unit tests
  • Violates Single Responsibility: Manages its own lifecycle and business logic
  • Concurrency Issues: Requires careful implementation in multithreaded environments
  • Subclassing Challenges: Difficult to extend

When to Use

Use the Singleton Pattern when:

  • There must be exactly one instance of a class
  • The instance must be accessible from multiple points in the application
  • The single instance should be extensible by subclassing

Common use cases:

  • Configuration managers
  • Connection pools
  • Thread pools
  • Caches
  • Logging
  • Device drivers

Alternatives to Consider

  • Dependency Injection: Pass dependencies explicitly instead of using singletons

  • Static Utility Classes: For stateless utilities (Math, Collections)

  • Enum Singleton (Java-specific): Thread-safe, serialization-safe, prevents reflection attacks

    public enum Singleton {
        INSTANCE;
        // methods here
    }

Important Notes

Serialization

Standard singleton implementations can be broken during deserialization. To prevent this, implement:

protected Object readResolve() {
    return getInstance();
}

Reflection

Reflection can be used to access private constructors. Enum singletons are immune to this.

Classloaders

Multiple classloaders can create multiple instances. Be aware in complex applications.

Design Principles

The Singleton Pattern demonstrates:

  • Encapsulation: Hides the creation logic
  • Single Responsibility (debatable): Manages both its instance and business logic