Design Pattern 1

1. Creational Pattern: Singleton

Design Pattern 1
Play this article

What is this?

In software design patterns, a Singleton is a creational design pattern that ensures only one instance of a class is created and provides a global point of access to it.

In web development, a Singleton can be integrated to ensure that there is only one instance of a particular object or resource available to the entire application. This can help to reduce resource usage and improve performance.

For example, a database connection is a resource that can benefit from being implemented as a Singleton in a web application. By creating a single instance of the database connection object and sharing it across the application, you can reduce the overhead of creating and tearing down connections for each request.

To integrate a Singleton in web development, you can create a class with a private constructor that creates a single instance of the object and provides a static method to access that instance. This ensures that only one instance of the object is ever created and that it can be accessed globally throughout the application.

In C# Asp.Net, you can create a Singleton using the Singleton Design Pattern or by using Dependency Injection frameworks like Ninject, which can manage the lifetime of objects and ensure only one instance is created.

public class DatabaseConnection
{
    private static DatabaseConnection instance;
    private string connectionString;
    private SqlConnection connection;

    // Private constructor to prevent creation of new instances
    private DatabaseConnection()
    {
        connectionString = "your_connection_string_here";
        connection = new SqlConnection(connectionString);
    }

    // Static method to access the Singleton instance
    public static DatabaseConnection GetInstance()
    {
        if (instance == null)
        {
            instance = new DatabaseConnection();
        }
        return instance;
    }

    // Method to get the database connection object
    public SqlConnection GetConnection()
    {
        return connection;
    }
}

n this example, the DatabaseConnection class is a Singleton with a private constructor that creates a new database connection object. The GetInstance() method ensures that only one instance of the DatabaseConnection class is ever created, and the GetConnection() method provides access to the database connection object.

To use the DatabaseConnection Singleton in your Asp.Net application, you can call the GetInstance() method to get the instance of the Singleton, and then call the GetConnection() method to get the database connection object:

DatabaseConnection connection = DatabaseConnection.GetInstance();
SqlConnection dbConn = connection.GetConnection();
// Use the dbConn object to interact with the database

DatabaseConnection connection = DatabaseConnection.GetInstance(); SqlConnection dbConn = connection.GetConnection(); // Use the dbConn object to interact with the database

Here's an example of implementing a Singleton pattern for a database connection in .NET 6 using the built-in dependency injection container that shows how to add the configuration in the Program.cs file and register the DatabaseConnection class as a Singleton:

using Microsoft.Extensions.Configuration;

public class DatabaseConnection
{
    private string connectionString;
    private SqlConnection connection;

    public DatabaseConnection(string connectionString)
    {
        this.connectionString = connectionString;
        connection = new SqlConnection(connectionString);
    }

    public SqlConnection GetConnection()
    {
        return connection;
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        var configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .Build();

        // Register the configuration and the DatabaseConnection class as a Singleton
        builder.Services.AddSingleton(configuration);
        builder.Services.AddSingleton<DatabaseConnection>((services) =>
        {
            var config = services.GetRequiredService<IConfiguration>();
            var connectionString = config.GetConnectionString("DefaultConnection");
            return new DatabaseConnection(connectionString);
        });

        var app = builder.Build();

        // Configure the app and add middleware
        // ...

        app.Run();
    }
}

In this example, we first create a ConfigurationBuilder and use it to build the configuration from the appsettings.json file.

Then, in the Main method, we register the configuration using the AddSingleton method and the DatabaseConnection class as a Singleton using the factory method. The factory method uses the IConfiguration object to get the connection string and create a new instance of the DatabaseConnection class.

Finally, we configure the app and add middleware before running it.

To use the DatabaseConnection Singleton in your application, you can inject it into your controller or service as before:

public class MyController : Controller
{
    private readonly DatabaseConnection _dbConnection;

    public MyController(DatabaseConnection dbConnection)
    {
        _dbConnection = dbConnection;
    }

    public IActionResult Index()
    {
        SqlConnection dbConn = _dbConnection.GetConnection();
        // Use the dbConn object to interact with the database
        return View();
    }
}

This way, you can ensure that only one instance of the DatabaseConnection object is created and shared throughout your .NET 6 application, improving performance and reducing resource usage.

Whether or not the Singleton pattern is a good choice depends on the specific use case and the context in which it's being used.

Singletons can be useful when you want to ensure that only one instance of a class is ever created and that instance is shared across the application. This can help reduce memory usage and improve performance by avoiding the overhead of creating multiple instances of the same object.

However, singletons can also introduce some challenges, such as making your code harder to test and potentially introducing dependencies and coupling between different parts of your application. They can also make it harder to change the behavior of your application in the future, since there may be multiple places in your code that rely on the same Singleton instance.

In general, it's best to use the Singleton pattern judiciously and consider alternative approaches where appropriate. If you do decide to use a Singleton, be sure to carefully consider the trade-offs and potential risks and design your code in a way that mitigates these issues.

Did you find this article valuable?

Support Nestor Rojas by becoming a sponsor. Any amount is appreciated!