A Complete Guide to Creational Design Patterns in Java: The Singleton Pattern

What is a design pattern?
A software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design.
Why should I learn patterns?
Makes life simpler by not reinventing the wheel
- Toolbox of time-tested solutions to common problems in software design.
- Defines a common language between the team and organization to solve emerging issues related to technological advancements.
- Start understanding patterns in libraries and languages.
Classification of patterns
Creational
Structural
Behavioral
There are 5 main types of Creational Design patterns:
- Builder
- Prototype
- Singleton
- Factory
- Abstract Factory
In this article, we will focus in detail on one of the Creational patterns — The Singleton Design pattern.
What YOU need to know?
- What is the Singleton pattern and why would you use it?
- How do you implement the Singleton pattern in Java?
- What is lazy & eager initialization in the Singleton pattern?
- How do you make a Singleton thread-safe?
- What is double-checked locking and how does it relate to the Singleton pattern?
Usage:
Ensures a class has only one instance and provides global access to that instance.
Useful when exactly one object is needed to coordinate actions across the system.
Existing problem:
Sometimes we need to have one and only one instance of our class.
Why?
The instance that requires instantiation only one time and can be reused throughout the program.
Example — Loggers, DB connection, drivers, configurations etc.
Sometimes we need to have one and only one instance of our class. Why?
- Resource Management: Some classes represent resources that are expensive to create or maintain, such as database connections or network sockets. Creating multiple instances of these classes can be wasteful and inefficient, as it can consume more resources than necessary. By ensuring that there is only one instance of the class, we can better manage the use of these resources.
- Consistency: Having multiple instances of a class can lead to inconsistencies in the application’s state. For example, if we have multiple instances of a configuration object, changes made to the configuration in one instance may not be reflected in the other instances. By ensuring that there is only one instance of the class, we can ensure that the state of the application remains consistent.
- Encapsulation: Some classes are designed to have a single point of entry, such as a logger or a cache. By ensuring that there is only one instance of the class, we can encapsulate the functionality of the class and prevent it from being used in unintended ways.
How can Singleton pattern help?
- Hide the constructor by making the default constructor private.
- Provide a static method that returns a reference to the instance.
Different approaches:
Below are the 4 different ways in which this pattern can be implemented.
Classic way—or lazy instantiation
Add synchronized keyword to make thread-safe
Eager instantiation
Double checked locking
Let’s understand each of the above approaches one by one.
Eager instantiation:
The easiest method to create a singleton class.
The instance of Singleton Class is created at the time of class loading.
This is not considered a ‘good’ practice because we should not create any instance beforehand unless invoked by the client.
Unless we are sure of the usage of this instance throughout the program, we should avoid using this pattern.
Classic Implementation:
Below is the sample code to implement lazy instantiation.
The instance is not initialized unless the getInstance() method is invoked.
The technique described above is effective in a single-threaded context, but it might lead to problems in multithreaded environments if many threads are running simultaneously inside the if condition. The singleton pattern will be destroyed, and both threads will receive different instances of the singleton class as a result.
Thread-safe Singleton:
Using the ‘synchronized’ keyword to make sure that only one thread at a time can execute getInstance().
The main disadvantage of this method is that using synchronized every time while creating the singleton object is expensive and may decrease the performance of your program.
Double-checked locking:
Instead of having a synchronised method, use a synchonized block within the code.
When the object is null, we can acquire the lock on the getInstance() method.
Reduces the overhead of calling the synchronized method every time.
Real World Scenarios
three real-world scenarios where the Singleton pattern might be useful:
- Database Connection: In a typical web application, multiple components may need access to a database connection. Creating a new database connection for each component can be time-consuming and resource-intensive. The Singleton pattern can be used to create a single instance of a database connection object, which can be shared by all components that need it.
- Configuration: In a large application, there may be many configuration settings that need to be read and used by different components. Rather than reading the configuration settings from a file or database multiple times, a Singleton configuration object can be created to read the settings once and provide them to all components.
- Logger: A logger is a common utility used to log messages and events from various parts of an application. By using the Singleton pattern, a single instance of the logger can be created and used by all components that need to log messages, rather than creating multiple instances and managing them separately.
Suggested books to read:
- Head First Design Patterns
2. Design Patterns: Elements of Reusable Object-Oriented Software
3. Head First Object-Oriented Analysis and Design
If you liked this article, please click the “clap” button 👏 a few times.
Gives me enough motivation to put out more content like this. Please share it with a friend who you think this article might help.
Follow me Varsha Das to receive my weekly articles.
Connect with me — Varsha Das | LinkedIn
Thanks for reading.
Happy learning! 😁