Singleton Design Pattern: Ensuring a Single Instance of a Class
The Singleton Design Pattern is a creational design pattern that ensures a class has only one instance and provides a global point of access to that instance. This is useful when you need to control access to shared resources, such as a database connection, configuration manager, or logging service.
Why Use the Singleton Pattern?
Single Instance: Ensures only one instance of a class exists in the application.
Global Access: Provides a global access point to that instance.
Resource Management: Helps manage shared resources efficiently.
Example: Logger Class
Let’s say you’re building a logging system for your application. You want to ensure that only one instance of the Logger
class exists, so all parts of the application log to the same file or console.
Step-by-Step Implementation
Step 1: Create the Logger
Class
The Logger
class will have a private constructor and a static method to get the single instance.
public class Logger {
// Step 2: Create a static instance of the class
private static Logger instance;
// Step 3: Make the constructor private to prevent instantiation
private Logger() {
System.out.println("Logger instance created.");
}
// Step 4: Provide a global access point to the instance
public static Logger getInstance() {
if (instance == null) {
instance = new Logger();
}
return instance;
}
// Step 5: Add methods to the class
public void log(String message) {
System.out.println("Log: " + message);
}
}
Step 2: Use the Singleton Logger
Now, you can use the Logger
class in your application. No matter how many times you call getInstance()
, it will always return the same instance.
public class Main {
public static void main(String[] args) {
// Get the singleton instance of Logger
Logger logger = Logger.getInstance();
// Log some messages
logger.log("Application started.");
logger.log("User logged in.");
// Check if it's the same instance
Logger anotherLogger = Logger.getInstance();
System.out.println("Are both instances the same? " + (logger == anotherLogger));
}
}
Output
Logger instance created.
Log: Application started.
Log: User logged in.
Are both instances the same? true
Key Points About the Singleton Pattern
Private Constructor: Prevents external instantiation of the class.
Static Instance: A static variable holds the single instance of the class.
Lazy Initialization: The instance is created only when needed (on the first call to
getInstance()
).Thread Safety: The above implementation is not thread-safe. For thread safety, you can use
synchronized
or other techniques.
Thread-Safe Singleton (Optional)
If your application is multi-threaded, you need to ensure that the Singleton instance is created in a thread-safe manner.
public static synchronized Logger getInstance() {
if (instance == null) {
instance = new Logger();
}
return instance;
}
Real-Life Analogy
Think of the Singleton Pattern like a CEO of a company. There’s only one CEO, and everyone in the company interacts with the same person for major decisions. Similarly, the Singleton Pattern ensures that only one instance of a class exists, and all parts of the application interact with that instance.
When to Use the Singleton Pattern?
When you need to control access to shared resources (e.g., database connections, configuration files).
When you want to ensure only one instance of a class exists.
When you need a global point of access to an object.