The Singleton design pattern ensures that a class has only one instance and provides a global point of access to that instance. This pattern is useful when exactly one object is needed to coordinate actions across the system.
Key Points to Remember:
- Private Constructor: The constructor is made
private to prevent direct instantiation from outside the class.
- Static Instance: The Singleton instance is
typically stored in a static field.
- Global Access: A static method is
provided to access the single instance of the class.
1. Basic Singleton
This is the simplest form of
Singleton, but it is not thread-safe.
public class Singleton {
private
static Singleton instance;
private Singleton() {
//
private constructor to prevent instantiation
}
public static Singleton getInstance() {
if
(instance == null) {
instance = new Singleton();
}
return
instance;
}
}
2. Thread-Safe Singleton (Double-Checked Locking)
To make the Singleton pattern thread-safe, you can use double-checked
locking. This approach is more efficient than synchronizing the entire getInstance
method.
public
class Singleton {
private static volatile Singleton instance;
private Singleton() {
// private constructor to prevent
instantiation
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
3. Eager Initialization
In this approach, the Singleton instance is created at the time of class
loading. This guarantees that the instance is created in a thread-safe manner
but may lead to resource wastage if the instance is never used.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
// private constructor to prevent
instantiation
}
public static Singleton getInstance() {
return instance;
}
}
4. Bill Pugh Singleton Design
This approach uses a static inner helper class to hold the Singleton
instance. The instance is created only when the SingletonHelper
class is loaded, which is thread-safe and efficient.
public
class Singleton {
private Singleton() {
// private constructor to prevent
instantiation
}
private static class SingletonHelper {
private static final Singleton INSTANCE
= new Singleton();
}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
5. Enum Singleton
Using an enum
to
implement the Singleton pattern is considered the most effective way. It is
simple, thread-safe, and ensures that the Singleton instance is only created
once.
public enum EnumSingleton {
INSTANCE;
public void
someMethod(String param) {
//
some class member
}
}
|
Here are some common real-time use cases:
1. Configuration Management
In many applications, configuration settings are read from a file or
environment variables and should be accessed globally. A Singleton can manage
these settings.
2. Logging
A logging system often needs to be accessible from multiple parts of an
application, and it usually involves writing to a file or console. The
Singleton pattern ensures that only one instance of the logger is used.
3. Database Connections
Managing database connections often requires a single, shared connection
pool to avoid the overhead of creating and closing multiple connections. A
Singleton can manage such a connection pool.
public class
DatabaseConnectionManager {
private static DatabaseConnectionManager instance;
private Connection connection;
private DatabaseConnectionManager() {
// Initialize database connection
}
public static DatabaseConnectionManager getInstance() {
if (instance == null) {
synchronized
(DatabaseConnectionManager.class) {
if (instance == null) {
instance = new
DatabaseConnectionManager();
}
}
}
return instance;
}
public Connection getConnection() {
return connection;
}
}
5. Cache Management
Caching frequently accessed data or computations can improve performance. A
Singleton can manage the cache to ensure it is consistent across the
application.
No comments:
Post a Comment