Different ways to create Singleton class in Java

Different ways to create Singleton class in Java
Introduction

Singleton classes play a crucial role in Java programming by ensuring that only one instance of a class exists and providing a global point of access to that instance. In this article, we’ll explore the top 5 different ways to create Singleton class in Java along with examples for each approach. Additionally, we’ll discuss the advantages and disadvantages of each method to help you choose the best approach for your Java projects.

Below are the different ways to create singleton class in Java

Eager Initialization

Eager initialization creates the Singleton instance eagerly during class loading, ensuring thread safety by initializing the instance statically.

Example:

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }
}

Advantages:

  • Thread safety: Eager initialization ensures that the Singleton instance is created eagerly during class loading, making it thread-safe.
  • Simple implementation: Eager initialization is straightforward to implement and understand.

Disadvantages:

  • Resource wastage: Eager initialization may lead to resource wastage if the Singleton instance is never used.
Lazy Initialization

Lazy initialization creates the Singleton instance lazily upon the first invocation of the getInstance() method, saving resources by initializing it only when needed.

Example:

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

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

Advantages:

  • Lazy initialization: Singleton instance is created lazily upon the first invocation of the getInstance() method, saving resources.
  • Thread safety: Synchronization ensures thread safety in a multi-threaded environment.

Disadvantages:

  • Synchronization overhead: Synchronization may introduce overhead, impacting performance, especially in high-concurrency scenarios.
Lazy Initialization (Double-Checked Locking)

Double-checked locking minimizes synchronization overhead by checking the instance variable twice, ensuring lazy initialization with reduced synchronization.

Example:

public class DoubleCheckedSingleton {
    private static volatile DoubleCheckedSingleton instance;

    private DoubleCheckedSingleton() {}

    public static DoubleCheckedSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedSingleton();
                }
            }
        }
        return instance;
    }
}

Advantages:

  • Lazy initialization with reduced synchronization overhead: Double-checked locking minimizes synchronization overhead by checking the instance variable twice.

Disadvantages:

  • Complexity: Double-checked locking is more complex and prone to subtle bugs, such as the “double-checked locking problem.”
Initialization on Demand Holder (IODH)

Initialization on Demand Holder leverages class loading and class initialization guarantees to achieve lazy initialization without synchronization.

Example:

public class IODHSingleton {
    private static class Holder {
        private static final IODHSingleton instance = new IODHSingleton();
    }

    private IODHSingleton() {}

    public static IODHSingleton getInstance() {
        return Holder.instance;
    }
}

Advantages:

  • Lazy initialization with thread safety: Initialization on Demand Holder leverages class loading and class initialization guarantees to achieve lazy initialization without synchronization.

Disadvantages:

  • Complexity: Initialization on Demand Holder involves the use of inner classes, which may increase code complexity.
Enum Singleton

Example:

public enum EnumSingleton {
    INSTANCE;

    // Add instance variables and methods here

    // Static block (optional)
    static {
        // Initialization code goes here
    }
}
EnumSingleton singleton = EnumSingleton.INSTANCE;

Advantages:

  • Thread safety and serialization: Enum singletons are inherently thread-safe and resistant to serialization/deserialization issues.
  • Conciseness: Enum singletons provide a concise and efficient way to implement the Singleton pattern.

Disadvantages:

  • Limited flexibility: Enum singletons cannot be extended or modified, limiting their flexibility compared to traditional classes.

You have learnt different ways to create singleton class in Java.

Advantages and Disadvantages of Singleton Class:

Advantages:

  1. Single Point of Control: Ensures that there is only one instance of the class in the JVM, providing a centralized point of control for the entire application.
  2. Improved Performance: Optimizes memory utilization and enhances performance by having a single instance of the class.
  3. Global Access: Provides a global point of access, making it easy to access the same instance of the class from anywhere in the application.
  4. Simplifies Resource Management: Simplifies the access and control of shared resources by providing a single instance for all components.
  5. Thread Safety: Ensures thread safety by controlling access to the single instance.

Disadvantages:

  1. Testing Difficulty: Testing a singleton class can be challenging as it tightly couples the class with the rest of the application, making isolation and testing complex.
  2. Tight Coupling: Singleton classes can become tightly coupled with the application, making it hard to modify or extend the class in the future.
  3. Global State: Maintains a global state, which can lead to unexpected behavior if not managed properly.
  4. Lacks Flexibility: Limits the flexibility of the class, as it can only have one instance, making it challenging to implement in scenarios where multiple instances are required.
  5. Scalability Concerns: Introducing a global state can reduce scalability and testability, as it introduces dependencies and coupling between different components.

By understanding the advantages and disadvantages of singleton classes, developers can make informed decisions when choosing to implement this design pattern in their Java applications.

Conclusion

In this article, we’ve explored the top 5 different ways to create singleton class in Java, along with examples, advantages and disadvantages of each approach. Whether you prioritize thread safety, performance or simplicity, understanding these different methods will help you choose the most suitable approach for your Java projects. Choose wisely and leverage the power of Singleton classes to build robust and scalable Java applications.

Share this article with tech community
WhatsApp Group Join Now
Telegram Group Join Now

Comments

No comments yet. Why don’t you start the discussion?

    Leave a Reply

    Your email address will not be published. Required fields are marked *