In this article we will learn about singleton pattern which is one of the creational pattern in gang-of-four patterns with java code examples.
Contents
- 1 Singleton Pattern’s Intent
- 2 Singleton Pattern’s Motivation
- 3 Singleton Pattern’s Applicability
- 4 Singleton Pattern’s Structure
- 5 Participants
- 6 Collaborations
- 7 Singleton Pattern’s Consequences
- 8 Singleton Pattern’s Implementation
- 9 Sample Code (Java Example)
- 10 Singleton Pattern’s Known Uses
- 11 Related Patterns
- 12 Non-Software Example
Singleton Pattern’s Intent
To create exactly one object of a class, and to provide global point of access to it.
Singleton Pattern’s Motivation
While developing applications, we will face frequent situations where there is a need to create exactly one instance of a class. For example, in a GUI application there is a requirement that there should be only one active instance of the application’s user interface.
No other instance of the user interface of the application should be created by the user. Another example is the requirement to maintain only one print spooler.
We need to allow the class to have exactly one instance and to allow a global point of access to it. How to do it? A global variable might allow you to provide global access to the object but it does not restrict you from creating multiple objects.
A better solution is to allow the class to take the responsibility of creating only one object and to provide a global point of access to it. This is what the singleton pattern does. The singleton pattern allows the class to create only one instance, allow other external objects to access that instance and does not allow the constructor to be invoked directly each time.
Singleton Pattern’s Applicability
Singleton Pattern can be used when:
- There must be exactly one instance of a class and to provide a global point of access to it.
- When the sole instance should be extensible by sub classing, and clients should be able to use the extended instance without modifying its code.
Singleton pattern can be used for developing in following situations:
- Logger classes
- Configuration classes
- Accessing resources in shared mode
- Factories implemented as Singletons
Singleton Pattern’s Structure
The structure of singleton pattern is as shown below:
Participants
Consists of a “Singleton” class with the following members:
- A static data member
- A private constructor
- A static public method that returns a reference to the static data member. This method is responsible for creating the single instance and providing the global access to that instance.
Collaborations
Clients access the singleton instance solely through the singleton’s class operation.
Singleton Pattern’s Consequences
- Controlled access to sole instance: As the instance is completely encapsulated in the class, we can have strict control on how the clients access it.
- Reduced name space: Avoids polluting the name space with global variables that store the single instances.
- Permits refinement of operations and representation: It easy to subclass and extend the functionality of the class method.
- Permits a variable number of instances: It is possible to create multiple instances by changing the code in the class method.
- More flexible than class operations: In C++, class methods cannot be overriden. Instance methods provides the flexibility of extending the operation in the subclass.
Singleton Pattern’s Implementation
The Singleton pattern defines a getInstace() class method which creates the new instance and is responsible for maintaining a single instance of the class.
It also provides global access to the clients as it will be a public method. The implementation code will be as follows:
class Singleton
{
private static Singleton instance;
private Singleton()
{
...
}
public static synchronized Singleton getInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
...
public void doOperation()
{
...
}
}
We can see from the above code that the getInstance() method ensures that only one instance of the class is created. The constructor must not be accessible from outside the class. So, it is made private.
The only way for instantiating the class is through getInstance() method. It is also responsible for providing a global point of access to the instance as shown below:
Singleton.getInstance().doSomething();
Specific problems and implementations:
Thread-safe implementation for multi-threading environment:
In a multithread application, multiple threads will be performing operations on a Singleton instance. To avoid undesired results, the Singleton class should provide a way to solve this problem.
As shown in the above code, the getInstance() is marked as synchronized to avoid read/write problems on the Singleton instance by multiple threads.
Lazy instantiation using double locking mechanism:
The implementation code provided above is thread-safe but it is not the best thread-safe implementation of Singleton. We can observe in the above code that when ever a new instance is created, in a multithreaded application, synchronization mechanisms are invoked as the method getInstance() is marked as synchronized.
So, this implementation code is not best in the performance dimension. To improve the performance, we should modify the above code in such a way that synchronization mechanism is invoked only when the instance is created for the first time.
This performance optimization involves a check whether an instance already exists in a non-synchronized block or not. If there is already an instance, return it. If not, a new instance is created inside a synchronized block after performing another check.
This process is known as double locking mechanism. Now, after implementing this strategy, the code will look as shown below:
//Lazy instantiation using double locking mechanism.
class Singleton
{
private static Singleton instance;
private Singleton()
{
System.out.println("Singleton(): Initializing Instance");
}
public static Singleton getInstance()
{
if (instance == null)
{
synchronized(Singleton.class)
{
if (instance == null)
{
System.out.println("getInstance(): First time getInstance was invoked!");
instance = new Singleton();
}
}
}
return instance;
}
public void doSomething()
{
System.out.println("doSomething(): Singleton does something!");
}
}
This double checking method is not supported in previous versions before java 5. For a universal solution, we can use the nested class approach.
Nested class solution by Bill Pugh:
This technique is known as initialization on demand holder. In this, a nested class is used to create the instance. This solution is thread-safe without requiring special language constructs like volatile and synchronized.
Since the nested class member will be final, the instance will be created only on its first reference. The code for this solution will be as shown below:
public class Singleton
{
// Private constructor prevents instantiation from other classes
private Singleton() { }
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder
{
public static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance()
{
return SingletonHolder.INSTANCE;
}
}
Early instantiation implementation using a static field:
In this Singleton’s implementation, instance of the class is created when the class is loaded by the class loader as the data member will be marked as static.
In this implementation, we don’t need any synchronization mechanisms. As the class is loaded only once, this will guarantee that the instance created is unique. Singleton’s implementation code using the early instantiation method is as follows:
//Early instantiation using implementation with static field.
class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
System.out.println("Singleton(): Initializing Instance");
}
public static Singleton getInstance()
{
return instance;
}
public void doSomething()
{
System.out.println("doSomething(): Singleton does something!");
}
}
There is a problem with this implementation which is a rare case. The problem is when a Singleton class in a package is loaded by two different class loaders.
Sub classing (Protected Constructor):
We can allow the Singleton class to be extended by allowing creation of sub classes to this class. This can be possible when the private constructor in the Singleton class is made protected.
This has two drawbacks:
1) If the constructor is made protected, another class in the same package can access it to create a new object. This defeats the purpose of a Singleton.
2) In the derived class or subclass, all the calls to the getInstance() method i.e., Singleton.getInstance() should be replaced with NewSingleton.getInstance().
Serialization:
If the Singleton class implements the java.io.Serializable interface, when a singleton is serialized and then deserialized more than once, there will be multiple instances of Singleton created.
In order to avoid this the readResolve method should be implemented. The code will be as follows:
public class Singleton implements Serializable
{
...
// This method is called immediately after an object of this class is deserialized.
// This method returns the singleton instance.
protected Object readResolve()
{
return getInstance();
}
}
Sample Code (Java Example)
Let us take a small practical example to understand the Singleton design pattern in more details.
Problem Statement:
Design a small ATM printing application which can generate multiple types of statements of the transaction including Mini Statement, Detailed statement etc. However the customer should be aware of the creation of these statements. Ensure that the memory consumption is minimized.
Design Solution:
The above requirement can be addressed using two core Gang of four design pattern – Factory design pattern and Singleton design pattern. In order to generate multiple types of statements for the ATM transactions in the ATM machine we can create a Statement Factory object which will have a factory method of createStatements(). The createStatements will create DetailedStatement or MiniStatement objects.
The client object will be completely unware of the object creation since it will interact with the Factory interface only. We will also create an interface called StatementType. This will allow further statement type objects e.g. Credit card statement etc to be added. So the solution is scalable and extensible following the object oriented Open/Closed design principle.
The second requirement of reducing the memory consumption can be achieved by using Singleton design pattern. The Statement Factory class need not be initiated multiple times and a single factory can create multiple statement objects. Singleton pattern will create a single instance of the StatementFactory class thus saving memory.
Code for StatementFactory class is as shown below:
public class StatementFactory extends Factory
{
private static StatementFactory uniqueInstance;
private StatementFactory() {}
public static StatementFactory getUniqueInstance()
{
if (uniqueInstance == null)
{
uniqueInstance = new StatementFactory();
System.out.println("Creating a new StatementFactory instance");
}
return uniqueInstance;
}
public StatementType createStatements(String selection)
{
if (selection.equalsIgnoreCase("detailedStmt"))
{
return new DetailedStatement();
}
else if (selection.equalsIgnoreCase("miniStmt"))
{
return new MiniStatement();
}
throw new IllegalArgumentException("Selection doesnot exist");
}
}
Singleton Pattern’s Known Uses
Following are the example usage of Singleton pattern in real world:
- Singleton pattern in Samlltalk-80, is the set of changes to the code, which is ChangeSet current.
- Relationship between classes and their metaclasses.
- InterViews user interface toolkit in Smalltalk uses the Singleton pattern to access the unique instance of its Session and WidgetKit classes.
Related Patterns
Other patterns like Abstract Factory, Builder and Prototype can be implemented using the Singleton pattern.
Example Singleton classes in java API:
- java.lang.Runtime
- java.awt.Desktop
Non-Software Example
The Singleton pattern ensures that a class has only one instance, and provides a global point of access to that instance. The Singleton pattern is named after the singleton set, which is defined to be a set containing one element.
The office of the President of the United States is a Singleton. The United States Constitution specifies the means by which a president is elected, limits the term of office, and defines the order of succession. As a result, there can be at most one active president at any given time.
Regardless of the personal identity of the active president, the title, “The President of the United States” is a global point of access that identifies the person in the office.
Suryateja Pericherla, at present is a Research Scholar (full-time Ph.D.) in the Dept. of Computer Science & Systems Engineering at Andhra University, Visakhapatnam. Previously worked as an Associate Professor in the Dept. of CSE at Vishnu Institute of Technology, India.
He has 11+ years of teaching experience and is an individual researcher whose research interests are Cloud Computing, Internet of Things, Computer Security, Network Security and Blockchain.
He is a member of professional societies like IEEE, ACM, CSI and ISCA. He published several research papers which are indexed by SCIE, WoS, Scopus, Springer and others.
Leave a Reply