14 Dec 2023
Advanced
The Singleton design pattern is a creational pattern that ensures a class has only one instance and provides a global point of access to that instance. It is commonly used when exactly one object is needed to coordinate actions across the system.
Here are some real-world examples of using the Singleton design pattern in C#:
Example 1: Database Connection
public class DatabaseConnection
{
private static DatabaseConnection _instance;
// Private constructor to prevent instantiation
private DatabaseConnection() { }
// Singleton instance property
public static DatabaseConnection Instance
{
get
{
if (_instance == null)
{
_instance = new DatabaseConnection();
}
return _instance;
}
}
// Other methods and properties for managing the database connection
}
Explanation:
- The
DatabaseConnectionclass has a private static field_instanceto hold the single instance of the class. - The constructor is private to prevent external instantiation of the class.
- The
Instanceproperty is a public static property that serves as the access point to the single instance. If an instance doesn't exist, it creates one; otherwise, it returns the existing instance.
Example 2: Logging Service
public class Logger
{
private static Logger _instance;
private static readonly object LockObject = new object();
// Private constructor to prevent instantiation
private Logger() { }
// Singleton instance property with thread safety using a lock
public static Logger Instance
{
get
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new Logger();
}
return _instance;
}
}
}
// Log method to perform logging
public void Log(string message)
{
// Log the message
}
}
Explanation:
- Similar to the previous example, the
Loggerclass has a private static field_instanceand a private constructor. - The
Instanceproperty uses a lock to provide thread safety during instance creation. - The
Logmethod is an example of a functionality that the singleton instance provides.
Example 3: Configuration Manager
public class ConfigurationManager
{
private static ConfigurationManager _instance;
private static readonly object LockObject = new object();
// Private constructor to prevent instantiation
private ConfigurationManager() { }
// Singleton instance property with thread safety using a lock
public static ConfigurationManager Instance
{
get
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new ConfigurationManager();
}
return _instance;
}
}
}
// Methods and properties for managing application configurations
// ...
}
Explanation:
- The
ConfigurationManagerclass follows the same pattern as the previous examples. - It has a private static field
_instanceand a private constructor to enforce the Singleton pattern. - The
Instanceproperty ensures that there's only one instance of theConfigurationManagerclass. - The class may have additional methods and properties for managing application configurations.
Example 4: User Authentication Manager
public class AuthManager
{
private static AuthManager _instance;
private static readonly object LockObject = new object();
private AuthManager() { }
public static AuthManager Instance
{
get
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new AuthManager();
}
return _instance;
}
}
}
public bool AuthenticateUser(string username, string password)
{
// Authenticate user logic
return true; // Placeholder logic
}
// Other authentication-related methods and properties
}
Explanation:
- The
AuthManagerclass is a Singleton responsible for handling user authentication. - The Singleton pattern ensures that there is only one instance of the authentication manager.
- The
AuthenticateUsermethod is an example of a functionality provided by the Singleton instance.
Example 5: Print Spooler
public class PrintSpooler
{
private static PrintSpooler _instance;
private static readonly object LockObject = new object();
private PrintSpooler() { }
public static PrintSpooler Instance
{
get
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new PrintSpooler();
}
return _instance;
}
}
}
public void AddPrintJob(string document)
{
// Add print job to the print queue
}
// Other print-related methods and properties
}
Explanation:
- The
PrintSpoolerclass is designed as a Singleton to manage print jobs in a print queue. - The Singleton pattern ensures a single point for handling print-related operations.
- The
AddPrintJobmethod is an example of a functionality provided by the Singleton instance.
Example 6: Notification Service
public class NotificationService
{
private static NotificationService _instance;
private static readonly object LockObject = new object();
private NotificationService() { }
public static NotificationService Instance
{
get
{
lock (LockObject)
{
if (_instance == null)
{
_instance = new NotificationService();
}
return _instance;
}
}
}
public void SendNotification(string message, string recipient)
{
// Send notification logic
}
// Other notification-related methods and properties
}
Explanation:
- The
NotificationServiceclass is a Singleton responsible for sending notifications. - The Singleton pattern ensures that there is only one instance of the notification service.
- The
SendNotificationmethod is an example of a functionality provided by the Singleton instance.