Last Updated on September 24, 2023 by KnownSense
The singleton design pattern is used to make sure a class has just one instance, and it helps you access that instance from anywhere in your code.
Imagine you’re working on a software application for a hospital. This application needs to manage patient records, appointments, and medical history. To ensure data consistency and prevent conflicts, you might use the Singleton pattern to create a single instance of a “PatientDataManager” class.
With the Singleton pattern, you can make sure that no matter where in the application the patient data is being accessed or modified, it always goes through the same instance of the “PatientDataManager.” This ensures that changes to patient records are synchronized and that there are no accidental duplications or conflicts in the data.
Benefits
- Single Instance: It guarantees that a class has only one instance throughout the application’s lifecycle. This can be useful for classes that control access to shared resources or manage global settings.
- Global Access: The Singleton instance is typically accessible from anywhere in the codebase, making it easy to access and utilize its functionalities without passing references around.
- Resource Management: It’s useful for managing resources that are expensive to create, such as database connections or network connections. The Singleton pattern ensures that these resources are created and initialized only once, saving time and memory.
- Data Consistency: In scenarios where you need to maintain data consistency across the application, the Singleton pattern can be used to centralize data access and modifications. This helps prevent data duplication or conflicting changes.
- Lazy Initialization: Singleton instances can be created lazily, meaning they’re only created when they’re actually needed. This can improve performance by avoiding unnecessary instance creation at startup.
- Controlled Access: Singleton allows you to control and manage access to shared resources or functionalities. It can provide a designated point for coordinating actions that involve the singleton instance.
- Easy Testing: While singletons can sometimes be challenging to test, they can also provide a consistent state for testing purposes. Mocking or replacing the singleton instance can help in testing various scenarios.
- Reduced Memory Footprint: Since there’s only one instance of the singleton class, memory consumption is reduced compared to creating multiple instances of the same class.
- Thread Safety: Singleton implementations can incorporate mechanisms to ensure thread safety, making them suitable for multi-threaded applications.
- Consistent Configuration: If you have a class responsible for configuration settings, the Singleton pattern can ensure that these settings are globally accessible and consistent.
UML of Singleton
Implementation
Here’s a simple implementation of the Singleton design pattern in Java for the hospital example. In this implementation, the instance variable is declared as volatile, which ensures that changes to it are immediately visible to other threads. The double null check is used to reduce the overhead of synchronization while still maintaining thread safety. The first null check is performed outside the synchronized block, and the second null check is performed inside the synchronized block. If the instance is still null inside the synchronized block, a new instance of PatientDataManager is created.
public class PatientDataManager {
// Private static instance variable
private static PatientDataManager instance;
// Private constructor to prevent external instantiation
private PatientDataManager() {
}
// Public static method to provide access to the instance using double null check
public static PatientDataManager getInstance() {
// First null check outside the synchronized block for performance improvement
if (instance == null) {
synchronized (PatientDataManager.class) {
// Second null check inside synchronized block to ensure thread safety
if (instance == null) {
instance = new PatientDataManager();
}
}
}
return instance;
}
public static void main(String[] args) {
// Accessing the singleton instance
PatientDataManager manager1 = PatientDataManager.getInstance();
PatientDataManager manager2 = PatientDataManager.getInstance();
// Both manager1 and manager2 refer to the same instance
System.out.println(manager1 == manager2);
}
}
OUTPUT
true
Conclusion
The Singleton pattern ensures a class has only one instance, provides global access to it, and is useful for managing shared resources, maintaining data consistency, and controlling access to critical functionality.