Design patterns are general reusable solutions to commonly occurring problems in software design. They provide developers with a way to solve recurring problems in a standardised way, leading to more efficient and maintainable code.
Singleton Pattern - Ensures that only one instance of a class is created and provides a global point of access to it.
Example - The Singleton pattern is used when we want to ensure that only one instance of a class exists and provide a global point of access to it.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton Instance {
get {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
In this implementation, the constructor of the Singleton class is private, which means that it cannot be called from outside the class. The only way to get an instance of the Singleton class is by calling the static Instance property.
// Please paste your code here and press Beautify button
Singleton instance1 = Singleton.Instance;
Singleton instance2 = Singleton.Instance;
// instance1 and instance2 refer to the same object
if (instance1 == instance2) {
Console.WriteLine("Only one instance exists.");
}
}
In this example, we create two instances of the Singleton class by calling the Instance property twice. Since the Instance property ensures that only one instance of the Singleton class exists, instance1 and instance2 refer to the same object.
Let's say we have a class DatabaseConnection that establishes a connection to a database. We want to ensure that only one connection to the database is created and shared across the entire application. To achieve this, we can use the Singleton pattern.
First, we create the DatabaseConnection class:
public class DatabaseConnection {
private static DatabaseConnection _instance;
private readonly string _connectionString;
private DatabaseConnection() {
_connectionString = "connection string here";
// code to establish database connection here
}
public static DatabaseConnection GetInstance() {
if (_instance == null) {
_instance = new DatabaseConnection();
}
return _instance;
}
public void ExecuteQuery(string query) {
// code to execute query here
}
}
The GetInstance() method checks if an instance of the DatabaseConnection class has already been created. If it has, it returns that instance. If it hasn't, it creates a new instance and returns it.
The ExecuteQuery() method can be used to execute SQL queries on the database.
Now, let's say we want to use the DatabaseConnection class in our application:
public class Program {
static void Main(string[] args) {
DatabaseConnection dbConn1 = DatabaseConnection.GetInstance();
DatabaseConnection dbConn2 = DatabaseConnection.GetInstance();
dbConn1.ExecuteQuery("SELECT * FROM users");
dbConn2.ExecuteQuery("SELECT * FROM orders");
if (dbConn1 == dbConn2) {
Console.WriteLine("Only one database connection exists.");
}
}
}
By using the Singleton pattern, we ensure that only one connection to the database is created and shared across the entire application, leading to more efficient and maintainable code.
We can use the Singleton pattern to achieve this:
public class ConfigurationManager {
private static ConfigurationManager _instance;
private readonly Dictionary < string, string > _settings;
private ConfigurationManager() {
// code to read configuration settings from file
_settings = new Dictionary < string, string > {
{
"setting1",
"value1"
},
{
"setting2",
"value2"
},
{
"setting3",
"value3"
}
};
}
public static ConfigurationManager GetInstance() {
if (_instance == null) {
_instance = new ConfigurationManager();
}
return _instance;
}
public string GetSetting(string key) {
if (_settings.ContainsKey(key)) {
return _settings[key];
}
return null;
}
}
The GetInstance() method checks if an instance of the ConfigurationManager class has already been created. If it has, it returns that instance. If it hasn't, it creates a new instance and returns it.
The GetSetting() method can be used to retrieve a configuration setting based on a key.
Now, let's say we want to use the ConfigurationManager class in our application:
public class Program {
static void Main(string[] args) {
ConfigurationManager config1 = ConfigurationManager.GetInstance();
ConfigurationManager config2 = ConfigurationManager.GetInstance();
string setting1 = config1.GetSetting("setting1");
string setting2 = config2.GetSetting("setting2");
if (config1 == config2) {
Console.WriteLine("Only one configuration manager exists.");
}
}
}
In this example, we create two instances of the ConfigurationManager class by calling the GetInstance() method twice. Since the GetInstance() method ensures that only one instance of the ConfigurationManager class exists, config1 and config2 refer to the same object.By using the Singleton pattern, we ensure that only one set of configuration settings is read from the file and shared across the entire application, leading to more efficient and consistent behavior.
The Singleton pattern consists of three components:
A private constructor - this prevents the class from being instantiated from outside the class.
A static property or method to retrieve the single instance of the class - this ensures that there is only one instance of the class and provides a global point of access to it.
A static field to hold the single instance of the class - this stores the single instance of the class that is created by the static property or method.
Let's consider a simple example to illustrate the use of the Singleton pattern. Suppose we have a class called Logger that logs messages to a file. We want to ensure that there is only one Logger object in our application, so we will use the Singleton pattern to achieve this.
Here is an implementation of the Logger class using the Singleton pattern in C#:
public class Logger {
private static Logger _instance;
private static readonly object _lock = new object();
private readonly string _logFileName;
private Logger() {
_logFileName = "log.txt";
}
public static Logger GetInstance() {
lock(_lock) {
if (_instance == null) {
_instance = new Logger();
}
}
return _instance;
}
public void Log(string message) {
using(StreamWriter writer = new StreamWriter(_logFileName, true)) {
writer.WriteLine($ "{DateTime.Now}: {message}");
}
}
}
The GetInstance() method checks if an instance of the Logger class has already been created. If it has, it returns that instance. If it hasn't, it creates a new instance of the Logger class and returns it. The method uses a lock to ensure that only one thread can access the method at a time.
The Log() method can be used to log messages to a file.
Now, let's consider an example of how we might use the Logger class in our application:
public class Program {
static void Main(string[] args) {
Logger logger1 = Logger.GetInstance();
Logger logger2 = Logger.GetInstance();
logger1.Log("Hello, world!");
logger2.Log("Goodbye, world!");
if (logger1 == logger2) {
Console.WriteLine("Only one logger instance exists.");
}
}
}
By using the Singleton pattern, we ensure that only one Logger object is created and shared across the entire application, leading to more efficient and consistent logging behavior.
I hope this explanation and example help clarify the Singleton pattern for you!
Factory Pattern - Provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.
Facade Pattern - Provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
0 Comments