Singleton design pattern using C#

5 minute read

Design Pattern

A software design pattern is a general, reusable solution to a commonly occurring problem in software design. Design patterns are typically documented in a standardized format, making it easy for developers to understand and apply them to their own software projects. It is like a template to solve a problem.

Singleton Design Pattern

The Singleton pattern is a design pattern that restrict to create object more than once and provides a global point of access to that instance. This pattern is useful when you want to ensure that only one instance of a class is created and used throughout the entire application.

The Singleton pattern is used when you want to:

  • Ensure that only one instance of a class is created.
  • Provide a single point of access to that instance.
  • Manage a shared resource.

Some downside of implementing the Singleton Pattern are

  • It can make unit testing more challenging since it introduces a global state to the application.
  • It limiting potential parallelism in the program through the use of locking.

In C#, there are several methods to implement a singleton pattern. The singleton pattern commonly includes the following attributes:

  • A single constructor that is private and has no parameters.
  • A sealed class.
  • A static variable that holds a reference to the single instance that is created.
  • A public and static method that provides access to the created instance.

Implementation of Singleton by C#

Step 1: Create EmployeeInfo class

This poco class is to hold employee information.


    public class Employee
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

Step 2: Create a singleton class

Here EmployeeService is a singleton class. Constructor of this class is private so that nobody can create its instance from outside. Instance() is a static method which creates instance of the singleton class. It actually forces that only one instance of the object will be created. Lock() is used to create instance of the singleton pattern in thread safe manner in multi threaded environment. The other two methods are used to add employee information in list and get employee salary. These two are as usual method.Don’t mix up Singleton class and Static class. Keep in mind; in static class everything must be static like Method, constructor, properties. But in singleton class it is not required. Hope, you will be clear after the following example.

    public sealed class SingletonEmployeeService
    {
        // singleton static object
        private static SingletonEmployeeService instance;

        // an object to use in a singleton class
        private List<Employee> employees = null;

        // Restrict to create object of singleton class
        private SingletonEmployeeService()
        {
            if(employees == null)
            {
                employees = new List<Employee>();
            }
        }

        // The static method to provide global access to the singleton object
        // Get singleton object of SingletonEmployeeService class
        public static SingletonEmployeeService GetInstance()
        {
            if (instance == null)
            {
                // Thread safe singleton
                lock (typeof(SingletonEmployeeService))
                {
                    instance = new SingletonEmployeeService();
                }
            }
            return instance;
        }

        // Add employee to the employees list
        public void AddEmployee(Employee employee)
        {
            employees.Add(employee);
        }

        // Get name of the employee by Id

        public string GetEmployeeName(int id) {
        
            string name = employees.Where(p => p.Id == id).First().Name;
            return name;
        }

    }

Here’s how the code works:

  • The class is marked as “sealed”, which means it cannot be inherited.
  • The class has a private static object named “instance”, which holds the reference to the single instance of the class.
  • The class also has a private List of Employee objects, which is the actual data that this class is managing.
  • The constructor of the class is marked as private, which means that it can only be called from within the class itself. This ensures that no other code can create an instance of the class.
  • The only way to access the singleton instance of the class is through the public static method named “GetInstance()”, which checks whether the instance has been created already. If not, it creates a new instance of the class in a thread-safe manner using a lock statement.
  • lock() is used to create instance of the singleton pattern in thread safe manner in multi threaded environment.
  • The class has two public methods, “AddEmployee()” and “GetEmployeeName()”, which can be used to add an employee to the employees list and to get the name of an employee by their ID, respectively.

Step 3: Access the singleton class

This class creates an instance of singleton class by EmployeeService objEmployeeService = EmployeeService.Instance(); and access singleton class.

    public class Program
    {
        static void Main(string[] args)
        {

            Employee emp1 = new Employee { Id = 1, Name = "John", Age = 30 };
            Employee emp2 = new Employee { Id = 2, Name = "Abraham", Age = 40};
            

            // Create singleton instance using GetInstance method not new
            SingletonEmployeeService singletonEmployeeService = SingletonEmployeeService.GetInstance();
            
            singletonEmployeeService.AddEmployee(emp1);
            singletonEmployeeService.AddEmployee(emp2);

            Console.WriteLine(singletonEmployeeService.GetEmployeeName(2));

            Console.ReadKey();
        }
    }

    // Output:
    // Abraham

This C# code shows an example of how to use the SingletonEmployeeService class to manage employee data. The main() method creates two Employee objects and adds them to the singleton instance of the SingletonEmployeeService class using the AddEmployee() method. It then retrieves the name of the employee with ID=2 using the GetEmployeeName() method and prints it to the console.

The key thing to note here is that the SingletonEmployeeService class is accessed using the GetInstance() method, rather than creating a new instance using the “new” keyword. This ensures that there is only one instance of the SingletonEmployeeService class in the application and that it is globally accessible.

The code creates two Employee objects with different ID, Name, and Age values and adds them to the employees list of the singleton instance using the AddEmployee() method. Then, it retrieves the name of the employee with ID=2 using the GetEmployeeName() method, which returns the name of the employee as “Abraham” and prints it to the console using the Console.WriteLine() method.

Overall, this code demonstrates how the Singleton pattern can be used to ensure that there is only one instance of a class in the application and how this instance can be accessed globally to manage data in a centralized manner.

Source code