Simplifying Design Patterns : Singleton

Simplifying Design Patterns : Singleton




Introduction

Design patterns are proven solutions to common software design problems. In this article, we’ll simplify the Singleton pattern—explaining how it works, when to use it, and how to implement it with clear examples. The examples are inspired by Refactoring Guru and Dive Into Design Patterns (Alexander Shvets), distilled to their essence.




How Does the Singleton Pattern Work?

The Singleton is a creational design pattern that ensures a class has only one instance and provides a global access point to it.



Example Scenario: A Restaurant Kitchen

Imagine a restaurant where:

  • There is a kitchen that needs only one oven for every dish
  • Instead of starting a new oven every time a dish is cooked, the kitchen reuses the existing one.
  • If the oven isn’t on yet, it gets started once. After that, every dish uses the same oven.

Everytime a dish is about to be cooked and the oven is called to start, it must check if it is already instantiated, if it is then the instance is returned if not the constructor must be called.



When to Use the Singleton Pattern?

Use this pattern when:

  1. You have a class in your program that should just have one single instance available, like a database object.
  2. You need strict control over global variables



How to Implement the Singleton Pattern



Step-by-Step (Restaurant Example)

  1. Define a Private Static Instance

    • The class holds its only instance in a private static field:
     private static Oven _instance;  
    
  2. Lock the Constructor

    • Make the constructor private to block external instantiation:
     private Oven()  
     {  
         IsOn = false; // Initialization logic  
     }  
    
  3. Create a Controlled Access Method

    • Provide a public static method (GetInstance) with lazy initialization:
     public static Oven GetInstance()  
     {  
         if (_instance == null)  
         {  
             _instance = new Oven(); // Creates instance only on first call  
         }  
         return _instance;  
     }  
    
  4. Add Thread Safety (Optional)

    • For multi-threaded kitchens, use lock or Lazy:
     private static readonly object _lock = new object();  
     // ...  
     lock (_lock)  
     {  
         if (_instance == null) _instance = new Oven();  
     }  
    
  5. Modern Approach: Use Lazy (Recommended)

    • Replace manual checks with C#’s built-in lazy initialization:
     private static readonly Lazy<Oven> _lazyOven = new Lazy<Oven>(() => new Oven());  
     public static Oven Instance => _lazyOven.Value;  
    



Diagram

Singleton Structure




Source link

Leave a Reply

Your email address will not be published. Required fields are marked *