A design pattern provides a general reusable solution to a common design problem.
These are well-tested solutions to common problems and issues we run into in software development. They are best practices for solving common software design problems that occur again and again.
There are many design patters, and they are categorized under three main categories: Structural, Behavioral, and Creational.
We’re not going to cover all of them for sure, but, some of them. Most of the commonly used ones are already explained in DesignPatterns (GitHub).
Design principles are guidelines that aim to achieve the desirable goals of a good design. Design patterns are solution for common design problems that use design principles to achieve these desirable goals of a good design.
Singleton pattern falls under the creational design patterns.
In your application, you may need to have only one instance of an object at any time. Singleton pattern ensures that there is only ever one single instance of a class, it prevents any other object from being instantiated from that class.
There are 3 different ways to implement the singleton pattern, each one has it’s own strengthens and pitfalls.
We are going to use Java for the purposes of demonstration.
This is the most simple way to implement the singleton pattern.
The idea is simple, having a static reference variable assigned to null initially, and then you check if it’s null, return new instance, if not, return the current reference variable. This is done inside a static method. So, no new object will be instantiated.
Remember to keep the constructor as a private, so you won’t allow object to be instantiated in any part of your application. The next snippet will make it more clear.
public class SingletonPattern {
private static SingletonPattern myInstance = null;
private SingletonPattern() {}
public static SingletonPattern getInstance() {
if (myInstance == null) {
myInstance = new SingletonPattern();
}
return myInstance;
}
}
In your main, or any part of the application, here is how you can get the latest instantiated object
SingletonPattern curInstance = SingletonPattern.getInstance();
This approach is not convenient when you have multi-threading. Next is a proper solution to this problem.
The solution is to have the method getInstance synchronized. It will ensure that there is no more than one instance from a class In a multi-threaded environment.
public static synchronized SingletonPattern getInstance() {
if (myInstance == null) {
myInstance = new SingletonPattern();
}
return myInstance;
}
But, you need to know that synchronization is expensive. It takes more time to run, and we’ll pay for this cost every time we call getInstance method. Here’s another solution opposite to eager instantiation.
Rather than doing check if myInstance is assigned to null or not, we assign it initially to a new instance. So, whenever the class is loaded by the JVM, the object will be created.
public class SingletonPattern {
private static SingletonPattern myInstance = new SingletonPattern();
private SingletonPattern() {}
public static SingletonPattern getInstance() {
return myInstance;
}
}
But, it also has it’s own pitfalls, what if the object won’t be always needed?, and what if the object is very heavy and complex, hence it will slow down the system?. This approach will create the object when the class is loaded even if it’s not needed.
It’s clear that there are trade-offs, it depends on your needs.
Use the classic approach if you don’t have multi-threading operations, and if you have, there are two other options.
One, if you don’t care about the performance issues of synchronization and the object won’t be always needed use the synchronized approach.
Two, if the object will be always needed, use the eager instantiation approach.