singleton design pattern

Singleton design Pattern in java with example and possible way to create Singleton Pattern

The Singleton Design Pattern ensures that a class has only one instance and provides a global point of access to that instance. It is often used when exactly one object is needed to coordinate actions across the system. Here’s an example of a Singleton Pattern in Java and then we’ll discuss possible ways to implement it:

Singleton design pattern example

Example# 1:

Example 1 - Singleton class/design pattern
/*
 * Author: Zameer Ali Mohil
 * */
public class Singleton {
    // Private static instance variable
    private static Singleton instance;

    // Private constructor to prevent instantiation from outside the class
    private Singleton() {
        // Initialization code, if any
    }

    // Public method to provide the global point of access to the instance
    public static Singleton getInstance() {
        // Lazy initialization: create the instance only if it doesn't exist
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    // Other methods and properties of the singleton class
    public void showMessage() {
        System.out.println("Hello, I am a Singleton!");
    }
}

public class SingletonPatternExample {
    public static void main(String[] args) {
        // Get the singleton instance
        Singleton singleton = Singleton.getInstance();

        // Use the singleton instance
        singleton.showMessage();
    }
}

In this example:

  • The Singleton class has a private static instance variable and a private constructor.
  • The getInstance() method provides the global point of access to the singleton instance.
  • The getInstance() method uses lazy initialization, creating the instance only if it doesn’t exist.
  • The main method in SingletonPatternExample demonstrates how to get the singleton instance and use it.

Example# 2:

Let’s consider a practical example where a Configuration class is implemented as a singleton. This class is responsible for storing configuration settings for an application, and having only one instance ensures that all parts of the application use the same configuration.

Example 2 - Singleton class/design pattern
/*
 * Author: Zameer Ali Mohil
 * */
public class Configuration {
    // Private static instance variable
    private static Configuration instance;

    // Configuration settings (example: database URL, API keys, etc.)
    private String databaseUrl;
    private String apiKey;

    // Private constructor to prevent instantiation from outside the class
    private Configuration() {
        // Default configuration settings
        this.databaseUrl = "jdbc:mysql://localhost:3306/mydatabase";
        this.apiKey = "your-api-key";
    }

    // Public method to provide the global point of access to the instance
    public static Configuration getInstance() {
        // Lazy initialization: create the instance only if it doesn't exist
        if (instance == null) {
            instance = new Configuration();
        }
        return instance;
    }

    // Getter and setter methods for configuration settings
    public String getDatabaseUrl() {
        return databaseUrl;
    }

    public void setDatabaseUrl(String databaseUrl) {
        this.databaseUrl = databaseUrl;
    }

    public String getApiKey() {
        return apiKey;
    }

    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }
}

public class SingletonPatternExample {
    public static void main(String[] args) {
        // Get the singleton instance of Configuration
        Configuration config = Configuration.getInstance();

        // Use the singleton instance to get and set configuration settings
        System.out.println("Database URL: " + config.getDatabaseUrl());
        System.out.println("API Key: " + config.getApiKey());

        // Modify the configuration settings
        config.setDatabaseUrl("jdbc:mysql://newhost:3306/newdatabase");
        config.setApiKey("new-api-key");

        // Access the modified settings through the same instance
        System.out.println("Modified Database URL: " + config.getDatabaseUrl());
        System.out.println("Modified API Key: " + config.getApiKey());
    }
}

In this example:

  • The Configuration class is a singleton that stores configuration settings.
  • The getInstance() method is used to get the singleton instance of Configuration.
  • The configuration settings can be accessed and modified using getter and setter methods.
  • The SingletonPatternExample class demonstrates how to use the singleton instance to access and modify configuration settings.

This example illustrates how the Singleton Pattern ensures that there is only one instance of the Configuration class throughout the application, allowing consistent access to configuration settings from different parts of the code.


Possible Ways to Implement Singleton Pattern:

1. Lazy Initialization: This is the most common way to implement a singleton. The instance is created only if it is needed for the first time.

Example

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

2. Eager Initialization: In this approach, the instance is created when the class is loaded, whether it is needed or not. It ensures thread safety at the cost of early initialization.

Example

private static Singleton instance = new Singleton();

public static Singleton getInstance() {
    return instance;
}

3. Thread-Safe Singleton (Double-Checked Locking): This approach ensures thread safety in a multithreaded environment. It uses double-checked locking to reduce the overhead of acquiring a lock every time.

Example

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

4. Bill Pugh Singleton Design: This is a modern way to implement the singleton pattern using a static inner helper class. It provides lazy initialization and thread safety without the need for synchronization.

Example

public class Singleton {
    private Singleton() {
        // Initialization code, if any
    }

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

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

5. Enum Singleton: Enums provide a concise way to create a singleton in Java. Enums are inherently serializable and thread-safe.

Example

public enum Singleton {
    INSTANCE;

    // Other methods and properties of the singleton
    public void showMessage() {
        System.out.println("Hello, I am an Enum Singleton!");
    }
}

Choose the appropriate method based on your requirements. The lazy initialization approach is commonly used as it balances between resource utilization and thread safety. The enum singleton is also a recommended approach in modern Java for its simplicity and inherent thread safety.

Leave a Reply

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