Interview Questions: Singleton Pattern vs the Static Keyword
Tags: design, software, architecture, interview
Published: 2022-03-04 14:46:11

## Introduction

If you've been in the tech industry for a while, you've certainly heard about the buzz words: "Design Patterns", maybe you've also heard about a famous pattern, the **Singleton**. Additionally, if you've been coding for a brief period, I'm hundred percent sure you've used the keyword **`static`** in one or more of your favorite programming languages.

For all of you experienced techies, you might already recognize that **"Singletons"** are used to create **one and only one** instance object of a class.

Hello World! once again, today with another interesting programming topic, let's discuss the differences between using the keyword **`static`** and implementing the **Singleton Design Pattern**.

Tech explanation aside, I want to quickly point out that I was hit by question lately while interviewing for a .NET Developer role in a software house, luckily I was prepared because it has popped into my mind a while ago before the interview itself.
Anyways, **this is an interview question**, so ladies and gentlemen, start taking notes.

I'm going to host my discussion **in C#** since it is a really powerful programming language, and it is in fact [similar to other famous languages like Java and C++](https://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java#:~:text=C%23%20and%20Java%20are%20similar,like%20C%20and%20C%2B%2B.), just keep in mind that what's written in this blog should apply **to any OOP language**, so pick your favorite, and hop on. 

## The `static` Keyword

We normally use the static keyword *(in C#)* in order to declare:
- Static Classes
- Static Class Members, such as:
    -  Constructors
    -  Fields
    -  Properties
    -  Methods
    
This specific type of declaration is useful when only one copy of the object (class or class members) is needed that single instance is shared **globally** among all other objects, [in other words](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/static) the static variable **belongs to the type itself** rather than to a specific object created from that type.

Let me throw a real-life example to make things a little bit clearer.
I love Mustangs, the Ford cars of course *(who doesn't!)*...

![](https://i.imgur.com/51t7IvN.jpg)

Let's say we are developing a game, and we want to model this type of car on its own class, what are the properties that we should include?

I'm thinking:
- Color
- Body type (hatchback or regular)
- Top Speed (could differ depending on the model)
- First year of production (1965)
- Year Model
- Logo

Now, we know that "First year of production" for this type of car will **always** be 1965, also the "Logo", it's the same for all cars. Now let's say Ford decides to modify the logo for some reason, it should be changed for all cars, right?
These two variables are perfect candidates for static variables.
Other variables should depend on the car itself (the object) and could differ for every single one.

```csharp
class Mustang 
{
    public string Color { get; set; }
    public bool IsHatchback { get; set; }
    public int TopSpeed { get; set; }
    public int YearModel { get; set; }
    public static int FirstYearInProduction { get; set; } = 1965;
    public static string LogoURL { get; set; } = "https://ford.com/logo.png";
}
```

See how the compiler complains when trying to access the **static variable** from an **instance object**?

![](https://i.imgur.com/3K6b37R.png)

Which makes sense actually, why would I ask about the first production year using my car, or my friend's car, **it's all the same at the end**, right?

So in a way, `FirstYearInProduction` and `LogoURL` are being singleton-like in their nature, same value for all instances, right?

Like fields and properties, **static methods** also belong to the type itself.
.. and for the sake completeness of this article, let me list down the features of static classes in C#:
- They can only contain static data members.
- It is not allowed to create objects of the static class.
- Static classes are sealed (could not be inherited from).

Okay, now that we've scratched the surface of the **`static` keyword** in most programming languages, now let's discuss what a **Singleton Pattern** means in order to formulate a rational comparison. 

**But wait, what are design patterns in the first place⁉️**

## Design Patterns
According to [refactoring.guru](https://refactoring.guru/design-patterns):
> Design patterns are typical solutions to common problems
in software design. Each pattern is like a **blueprint**
that you can customize to solve a particular
design problem in your code.

Design Patterns comes in different sizes and shapes, and they can be categorized into 3 main types:

1. **Creational:** These patterns are designed for class instantiation. They can be either class-creation patterns or object-creational patterns.

2. **Structural**: These patterns are designed with regard to a class's structure and composition. The main goal of most of these patterns is to increase the functionality of the class(es) involved, without changing much of its composition.

3. **Behavioral**: These patterns are designed depending on how one class communicates with others.

## Singleton Design Pattern
Now, let's get back to our main subject, the Singleton Pattern.

Singletons are not part of a specific language (not a keyword for example) or do they belong to frameworks. Singletons are just special classes built in a special way to fit in a special use case.. 
*Lot of "specials", huh?* That's the case with most modern design patterns.

The pattern's main objective is to create only one instance of a class and to provide **only one global access point** to that object.

As you might've guessed, this description fits nicely into the **Creational patterns** category, because at the end, we are **"creating"** an object, with only a "**single**" instance.

So filling in the gaps of Refactoring Guru's definition stated above, the current design problem at hand is that **we need to create only one instance of the object**, that's why we've chosen the Singleton Design Pattern.

### Singleton Implementation in **C#**
Now I'm going to write down a couple of versions of Singletons in C#, let's start first by the simplest one, a **Naïve** one if you will, and I'm going to explain why it wouldn't hold up in tough environments in a moment.

#### Naïve Singleton

```csharp
public sealed class NaiveSingleton
{
    private static NaiveSingleton _instance;
    
    private NaiveSingleton() { }

    public static NaiveSingleton GetInstance()
    {
        if (_instance == null)
        {
            _instance = new NaiveSingleton();
        }
        return _instance;
    }

    public void someBusinessLogic()
    {
        // ...
    }
}
```

First up, **notice the `sealed` keyword**, Singletons should always be a **"sealed"** in order to prevent class inheritance, which could end up with multiple instances and this contrasts the whole point of Singletons.

Also, the constructor must be private to prevent creating **`new`** instances.

**Now the `GetInstance()` method**, this is the main entry point for the class, it serves as an alternative to the constructor *(which we hid using the **`private`** keyword)* and lets clients access the same instance of this class over and over. 
On the first run, it creates a singleton object and assigns it into the static field **`_instance`**. 
On subsequent runs, it returns the existing object stored in the static field.

To test our code, we could run this snippet on the `main()` function of our console application:

```csharp
static void Main(string[] args)
{
    NaiveSingleton s1 = NaiveSingleton.GetInstance();
    NaiveSingleton s2 = NaiveSingleton.GetInstance();

    if (s1 == s2)
    {
        Console.WriteLine("Singleton works, both variables contain the same instance.");
    }
    else
    {
        Console.WriteLine("Singleton failed, variables contain different instances.");
    }
}
```

And the output should be as expected:
```
Singleton works, both variables contain the same instance.
```

Great, both `s1` and `s2` are essentially the same, right? Ummm, not always.

*Of course, there's a culprit, it shouldn't be that straightforward huh? 😁*

#### Why isn't our solution sophisticated enough?
To better explain my point, let me adjust our `main()` function a little bit and introduce some asynchrony into the problem.

**⚠️ Disclaimer:** The following part is a little bit advanced *(just a little bit, I promise)* and needs some basic understanding of the asynchronous operation in C#, if you don't feel comfortable with `async`, `await` and C# Tasks, feel free to check my **[DEV.TO series about the topic](https://dev.to/paulafahmy/series/12755)** where I attempt to make a simple cup of tea, **asynchronously**.

Back to our `main()` function:

```csharp
static void Main(string[] args)
{
    // Delay getting an instance of our singleton by doing so inside a task.
    Task<NaiveSingleton> ts1 = Task.Run(() => NaiveSingleton.GetInstance());
    Task<NaiveSingleton> ts2 = Task.Run(() => NaiveSingleton.GetInstance());

    // Run both tasks in parallel
    await Task.WhenAll(ts1, ts2);

    // Get the result of each task
    NaiveSingleton s1 = await ts1;
    NaiveSingleton s2 = await ts2;

    if (s1 == s2)
    {
        Console.WriteLine("Singleton works, both variables contain the same instance.");
    }
    else
    {
        Console.WriteLine("Singleton failed, variables contain different instances.");
    }
}
```

The main point of the previous modification is to access the `GetInstance()` method of the Singleton from two different ***"contexts"*** at the same time, for example, two different threads.

**📝 Side Note:** The previous modification might have not essentially created a whole new thread, but it certainly accessed the `GetInstance()` method from two different contexts, for an explanation, read through [this StackOverflow answer](https://stackoverflow.com/a/4130347/9312267), you can check [this shorter one too](https://stackoverflow.com/a/4130204/9312267) on the same question.

Now, let's check the output of the previous modification:
```
Singleton failed, variables contain different instances.
```

**So, what happened?**
Check the comments within the snippet for clarifications
```csharp
public static NaiveSingleton GetInstance()
{
    // Both contexts entered the GetInstance() method at the same time,
    // both of them queried whether _instance is null at the same time,
    // and since _instance was in fact initially null,
    // both succeeded to enter the if clause at the same time 
    if (_instance == null)
    {
         // .. which resulted in the creation of a new Instance 
         // twice for each context
        _instance = new NaiveSingleton();
    }
    return _instance;
}
```

Let's fix this small bug, and make our Singleton a little bit more Sophisticated.

#### Sophisticated Singleton

```csharp
public sealed class SophisticatedSingleton
{ 
    private static SophisticatedSingleton _instance; 
    private static readonly object _lock = new object(); 
    
    private SophisticatedSingleton() { } 

    public static SophisticatedSingleton GetInstance()
    {
        lock (_lock)
        {
            if (_instance == null)
            {
                _instance = new SophisticatedSingleton();
            }
        }
        return _instance;
    }
}
```

Straight up, we could notice a couple of lines making this version a little different than its Naïve sibling.

Simply speaking, I've added a lock object and utilized it using C#'s **`lock()` keyword**, this will be used to **synchronize threads** during first access to the Singleton.

During the initial launch of the program, there are no instances yet, multiple contexts (caused by the `Task.WhenAll()` call) will simultaneously reach the lock at the same time. 
The first of them will acquire it and will proceed further creating an instance, while the others will wait for the lock to be released.

Once the first context leaves the lock block, another context that might have been waiting for the lock release will then enter this section.
This time the Singleton field is already initialized and there would be no further need to initialize it once more with a new instance.

Now let's test our fix, I'll replace references to the `NaiveSingleton` in our `Main()` method and migrate to the newer `SophisticatedSingleton`:

```csharp
static void Main(string[] args)
{
    // Delay getting an instance of our singleton by doing so inside a task.
    Task<SophisticatedSingleton> ts1 = Task.Run(() => SophisticatedSingleton.GetInstance());
    Task<SophisticatedSingleton> ts2 = Task.Run(() => SophisticatedSingleton.GetInstance());

    // Run both tasks in parallel
    await Task.WhenAll(ts1, ts2);

    // Get the result of each task
    SophisticatedSingleton s1 = await ts1;
    SophisticatedSingleton s2 = await ts2;

    if (s1 == s2)
    {
        Console.WriteLine("Singleton works, both variables contain the same instance.");
    }
    else
    {
        Console.WriteLine("Singleton failed, variables contain different instances.");
    }
}
```

And here goes our expected output:
```
Singleton works, both variables contain the same instance.
```
***Hurray 🥳!***

#### Eager vs Lazy Initialization
There is yet one another customization to how you'd implement a singleton.

We've been initializing Singletons throughout the previous couple of examples **"lazily"**, which means that an instance would not be initialized unless the `getInstance()` function has been called and the `_instance == null` check returned true, only then would an instance be initialized, in other words, `_instance` would never be initialized unless at least one context needs it.

But what if we want the Singleton's instance to be available right away?

```csharp
public sealed class EagerSingleton
{
    private EagerSingleton() { }

    private static EagerSingleton _instance = new EagerSingleton();

    public static EagerSingleton GetInstance()
    {
        return _instance;
    }
}
```

A minor tweak to the original Naïve Singleton could be done, where we initialize the static `_instance` field inline, making it ready for usage right before needing it.

This has the benefit of making the instance ***instantly* available**, **but**, a major drawback should be accounted for. 

Eagerly initializing the field means that it would be initialized even if no one ever needs it, taking into consideration whether the instance itself might require heavy processing or a substantially large amount of memory bytes, this would certainly form an overhead for your application, so be sure to use this technique wisely.

## Use Cases of Singletons
Now I can think of a couple of real-life use cases, for example, we could design our own custom **Logger** class by it being defined as a singleton. No need to create a new instance every time we need to log something into the console or the database.

Speaking of databases, we could also build our database context using the Singleton Pattern, because again, no need for multiple instances, only one is enough.
[One would argue](https://stackoverflow.com/questions/228164/on-design-patterns-when-should-i-use-the-singleton#comment71466229_228168) that it would be better to register it as a service (depending on the dependency injection framework of your choice) and inject it to whatever the class that needs it, which is totally valid of course, but for simple projects, I think it would be perfectly fine to design the context as a Singleton.

In addition to database connections and logging services, Singleton classes could also be used for driver objects, caching, or thread pools.

## Takeaway 📒
So to answer the main question:
### What are the similarities and differences between the two approaches?
As you might've already noticed, a Singleton is nothing but some wrapping methods around a core static field packaged into a **`sealed`** class that has no public constructors.

A static field indeed helps in making an object globally accessed, but by itself, it neither does help in making it **threadsafe** nor **lazily constructed**, it does not introduce **encapsulation** into the game, meaning you'll access the field directly without a custom **"getter"** *(like `getInstance()` method in our case)* and it might be dangerous to expose the field like so in some cases.

**Here are some key differences that could also be included in our research:**
1. A Singleton can **implement interfaces** and **inherit** from other classes. While a **static class cannot** inherit their instance members. So Singleton is more flexible than static classes and can maintain state.
2. A Singleton can be initialized lazily, while a static class is generally initialized when it is first loaded.
3. Singleton Objects are stored on the **heap** while static classes are stored in **stack**.
4. Singleton Objects can **dispose** but static classes can't.
5. Singleton Objects can **clone** but static classes can't.

**To sum up 📒**, I could use this answer from [Stackoverflow](https://stackoverflow.com/a/4566209/9312267):

> Static classes are not for anything that needs state. It is useful for putting a bunch of functions together i.e Math (or Utils in projects). So the class name just gives us a clue where we can find the functions and nothing more.

So whenever you need to choose between the two approaches, ask yourself the following question:

**If there is a bunch of functions that should be packaged together**: go for static.
Anything else which needs **single access to some resources and state maintaining**, singleton should be the way to go.

**Side Note 🗒️:**
Singletons are sometimes considered as **anti-patterns**, here's why:

As we've discussed, Singletons are basically a way to use global variables, global variables are bad because any code anywhere in the system can change their values. So when debugging, it can be challenging to figure out which code path leads to the Singleton's current state.
The previous problem can be handled by proper encapsulation mechanisms though, just be a little bit mindful about how you implement them.

I'd recommend reading this [StackOverflow](https://stackoverflow.com/questions/12755539/why-is-singleton-considered-an-anti-pattern) thread about the topic.


## Outro
A Singleton class is a pattern, one of many in fact. It would be a great idea to read more about other design patterns too, [Refactoring Guru](https://refactoring.guru/design-patterns) hosts explanations to most of them in a nicely illustrated way, be sure to check them out.

It was my pleasure to conduct this research, and I hope you'd find it interesting and informative. In case you have something on your mind, let's discuss it in the comments section.

Keep Coding 💻!
See you soon. 👋