Codiwan.com

The blog for Design Patterns, Linux, HA and Myself!

Singleton Design Pattern With Real World Example In Java

Singleton Pattern or Singleton Design Pattern: Learn Singleton Design Pattern with a real world example by creating a Configuration Manager

This document presents a simple tutorial for the Singleton Design Pattern. We’ll start by creating a Config Manager and afterwards we’ll try to find the problems in its implementation, and the use the Singleton Design Pattern to solve those problems.

This document is divided into three stages:

Note: Make sure to go through the code comments as well. It’ll help you understand the concept better.

Stage 1

Here we begin the chapter of Singleton Design Pattern.

The requirements for the Config manager are:

Here is a very simple implementation based on the requirements that we’ve received:

/**
 * This the config manager.
 * The actual configuration properties are present in the HashMap configMap.
 */
class ConfigManager {

    private Map<String, String> configMap = new HashMap<String, String>() {{
        put("host", "internal.db");
        put("port", "8179");
        put("user", "admin");
        put("password", "pa$$w0rD");
    }};

    /**
     * This method updates the configuration by adding the new key and value pair to the configMap
     *
     * @param key   name of the key
     * @param value value for the key
     * @return previous value
     */
    public String update(String key, String value) {
        return configMap.put(key, value);
    }

    /**
     * @param key key for which the value is to be retrieved
     * @return value, null if not present
     */
    public String get(String key) {
        return configMap.get(key);
    }
}
Stage 2

So what could be the problems in our implementation? Well, there can be multiple objects of ConfigManager class and due to that there can be multiple values for the same key among the multiple objects. For example,

    ConfigManager configManager1 = new ConfigManager();
    ConfigManager configManager2 = new ConfigManager();
  
    configManager1.update("password", "NĒwAndImPr0vĒD");
  
    // this password is not equal to "NĒwAndImPr0vĒD"
    String password = configManager2.get("password");

The behaviour of this class requires it’s object to be used in Singleton mode. That is, only one object throughout the process lifetime.

Let’s re-implement our Config Manager so that only one instance of this class can be created.

/**
 * This config manager now has a private constructor.
 */
class ConfigManager {

    public static ConfigManager instance;

    private Map<String, String> configMap = new HashMap<String, String>() {{
        put("host", "internal.db");
        put("port", "8179");
        put("user", "admin");
        put("password", "pa$$w0rD");
    }};

    /**
     * There's a private constructor as we don't want any object of this class created anywhere outside this class
     */
    private ConfigManager() {

    }

    /**
     * This method updates the configuration by adding the new key and value pair to the configMap
     *
     * @param key   name of the key
     * @param value value for the key
     * @return previous value
     */
    public String update(String key, String value) {
        return configMap.put(key, value);
    }

    /**
     * @param key key for which the value is to be retrieved
     * @return value, null if not present
     */
    public String get(String key) {
        return configMap.get(key);
    }

    /**
     * This block is synchronized as we want the threads to access this method one at a time.
     *
     * @return the singleton instance of the Config Manager
     */
    public static synchronized ConfigManager getInstance() {
        if (instance == null) {
            instance = new ConfigManager();
        }
        return instance;
    }
}
Stage 3

Now we’ve only one method that is initializing the object and as the constructor is private, this instance cannot be initialized outside the class.

You might notice that we’ve made the method synchronized because we don’t want multiple initialization of the object. However, after the first time(after the object is initialized) synchronization is becoming an unnecessary evil. If that is a cause of concern for you then there are two possible solutions for that:

Finally the definition from the Wikipedia

In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one “single” instance. This is useful when exactly one object is needed to coordinate actions across the system.

I’ve created these tutorials after learning Design Patterns from this book Head First Design Patterns (A Brain Friendly Guide).

Loading Comments... Disqus Loader
comments powered by Disqus