Considering the Singleton

When should I use it? When should I avoid it?

Micha Davis
5 min readMay 12, 2021

I’m not gonna lie, I was super eager to learn about design patterns. When I first started learning to code as a kid I had no notion of how to structure a program. If a program I clumsily adapted out of the back of a book didn’t work like I expected, there was almost no chance I would be able to find what broke or figure out how to fix it.

So, now that I’m seriously learning, I was very interested to know more about these mysterious, arcane patterns. But the closer I got to understanding design patterns the more I learned that their chief purpose is to cause arguments among developers. And the one everyone loves to hate or (hates to love) is the Singleton.

What is the Singleton design pattern?

It’s a way to solve two problems at once.

First problem: very often you’ll find yourself with a class that you are constantly referencing from other scripts. This involves creating a variable handle, finding the game object containing the class, and null checking to make sure you didn’t just grab a handful of nothing. To me, the null checking is the big one. That’s a lot of boilerplate.

The Singleton pattern provides a static global reference to an instance of a class. You only have to null check it once, and then the reference lives permanently in memory for the life of the program. For classes that orchestrate many elements of the game, such as a Game Manager class, this is a huge shortcut. But, of course that comes at the cost of devoting a chunk of memory to keeping the instance alive and waiting for your call. Speaking of instances…

Second problem: when you call a class into action, you’re actually calling a runtime instance of that class. The distinction is important, because if (for example) you have multiple asynchronous operations running, they are each their own instance of their class. Individual instances aren’t aware of what another instance does — meaning concurrent instances could cause conflicts if they are messing with the same information.

The Singleton pattern solves this by ensuring there is only ever one instance of a class.

When should I use it?

Some say never. The memory cost can be high, it’s a global variable which can be a huge pain to debug, t’s not multithread friendly, and it solves two problems when you might only have one or the other.

So, it seems that if you can afford the memory and you actually need both a global reference AND a singular instance of a class, a Singleton is an acceptable solution. But also maybe not. This is where most of the disagreement happens.

It’s easier to say when not to use it. There are many different ways to get a reference to a class — in fact, there may be some situations where you don’t need a “manager” class at all which saves you the trouble of finding a reference to it. Remember that in OOP, each object should be able to do as much of its own work as possible.

The Singleton in C#

Let’s assume you have a good use-case that satisfies the need for a singleton. What does it actually look like in code?

The first part, is a private static variable _instance of the data type for our class. In this example, it’s a UI manager.

It needs to be private, because in order for the instance control feature to work, only this class can be allowed to modify the _instance variable.

Next, we add a public property Instance to the class with the same type as the _instance variable. We only define the get for this property — again, we don’t want anyone else but this class to set the Instance.

Here we also null check the instance and return the private variable we assigned earlier to anyone trying to get this property.

Finally, we assign _instance to this class on awake, to make sure it starts in memory and stays there as the only instance of the class.

From there the class can be filled in as a normal class, with whatever methods and operations it needs to perform its function. Here’s a look at the full UI Manager for one of my prototypes:

You can see here I have two properties designed to further shortcut the process of adding or removing values to the UI. Now, if I want to change the UI display, all I have to do is drop this line where it is relevant to do so:

I don’t have to declare a reference variable (the variable has already been declared and assigned) I don’t have to null check (the UIManager has already been null checked), I don’t have to worry if there is a concurrent operation also trying to modify the same value in the UI (there’s only one UIManager instance that can set UpdateCoins). All in all, this Singleton seems to be a fantastic place to store any code that manipulates the UI.

… until the UI class gets too big for the memory budget, or the number of referents grows too large and bug hunting becomes too difficult. And then the final straw: it’s a pain to undo a Singleton that has grown unwieldly. You have to rebuild (and null check) all those references in each class.

Final considerations?

If all you need is a single instance, you can probably get away with a static class. If all you need is some amount of shared state but it doesn’t have to be global, maybe you can create a base class that subclasses can derive operations from. The Singleton is quick and easy for development, but used too liberally it can cause long-term problems in a large-scale project. Use with care, and be willing to explore options that better suit your long-term needs.

--

--

Micha Davis
Micha Davis

Written by Micha Davis

Unity Developer / Game Developer / Artist / Problem Solver

Responses (1)