The singleton creational pattern is simple and often used. It’s actually used a bit too often so this episode will give you some caution and provide some ideas to modify this pattern when needed.
There are really just 3 parts that make a class a singleton:
- Declare all constructors to be private. You may only have one constructor. The main thing is that you don’t leave any overloaded constructors accessible.
- Declare a public static method called instance or maybe getInstance that returns a pointer or a reference to an instance of the singleton class. This method will have access to the private constructor and will construct an instance of the singleton class when it’s first called. After that, it will just return the first instance that was created.
- Declare a private static data member that’s either a pointer or a reference to the singleton class. I say, or reference, because that may be the way some languages handle pointers. This is the data member that the instance method will use to store the first instance of the singleton.
This pattern is so simple that it’s used a bit too much. The main problem is that it’s actually little better than a global variable. It makes the single instance available throughout your program. For a large program, this can cause problems debugging because the singleton can be accessed and potentially modified from anywhere.
The singleton pattern is useful, just don’t overuse it. The podcast episode also gives you some additional tips for how you might want to modify this pattern. Listen to the full episode or you can also read the full transcript below.
The basic description says that this pattern ensures that there’s only one instance of a class and that there’s global access to that single instance.
First of all, why would anybody want to restrict the number of instances to just a single one? Some aspects of your program might represent services or features which really do exist just once. Maybe you only want one log file to ever be created. Or you have just a single database where you keep important information. Or you only want to ever open a single communication channel with a server computer. There will be times when you want to restrict instances like this and the singleton pattern shows you a simple way to accomplish this.
Let’s take this step-by-step. In order to ensure that there’s only one instance, we need some way to control access to what code can create instances. All we need is to protect the constructors. After all, if outside code can’t call the constructors, then it can’t create instances.
This means we need the constructors to be either protected or private. If the constructors are protected, then all some other code needs to do is derive from our class and it has full access to the constructors. Sure we won’t have instances of just this class everywhere, but instead, this class can be included as a base class instance in other classes. That’s not what this pattern describes.
The only way then to make sure that instances can never be created is to make all the constructors private. But, wait a minute. What good is a class that can never be constructed?
Remember that making a method private restricts access to that method from any code outside of the class itself. But other code in the class is allowed to call private methods.
There’s another important step needed to implement a singleton and for that, we need a static method. You can listen to episode #32 which describes static methods if you need to. A static method can be called even without creating an instance of the class. It will also have access to the private constructors even if the static method is itself public.
The static method is usually called instance or getInstance and it acts as a gatekeeper. You see, before it creates a new instance of the singleton class, it first checks if it’s ever been called yet and previously created an instance. If so, then it just returns the first instance that was created. If the instance method is called a second or a third time or the hundredth time, it still continues to return the same instance that was first created. The only time this method actually creates the singleton is on the very first request and then it just makes sure to save that instance in a private static data member so it will know what instance to return the next time.
You just need three things to implement a singleton:
◦ #1 Keep you constructors private. You may only need a single constructor, just keep it private.
◦ #2 Declare a public static method that returns either a pointer or a reference to the singleton class. Don’t return a copy or that defeats the whole purpose of this pattern.
◦ #3 Declare a private static pointer or reference to the singleton that the instance method can update the first time it’s called with the one and only instance.
This is one of the most simple patterns which may be why it’s used so often. It seems like a good thing to do right? Instead of creating a global variable, make it a singleton. The problem is that it’s still globally available anywhere. It really is little better than a global variable. I’ll show you some problems and some alternatives right after this message from our sponsor.
( Message from Sponsor )
The first thing that comes to mind is why just a single instance? What if you want to allow two instances? Or three? Or some other specific number?
If you find yourself needing exclusive access to an instance for a short while and then want to return that instance so that other code can use it once you’re done, then the singleton pattern is probably not a good fit. Take a library for example that has a specific number of each book. I don’t recommend that you try to use a singleton to keep track of each of the books.
When I say that you may want two or more instances, I’m still talking about unrestricted access to those instances from anywhere. You could accomplish this by adding some extra parameters to the instance method that allow you to customize each singleton. Then instead of the singleton having a single private static data member of the first instance, it can track an array of unique instances. This would let you ask for an instance of your singleton from anywhere and the singleton class would still act as a gatekeeper but this time, it would check if it had ever created an instance with the same set of configuration values before or not.
A singleton like this would allow you for example to manage several different log files and anytime some code asks for a log file that’s already been created, then that matching log file would be returned. If a new log file instance is requested, then the singleton would go ahead and create it and add the new log file to the list of log files being tracked.
A slightly more difficult problem though has to do with the global nature of singletons. Whether there’s just one or several, they’re still global. Anytime your program deals with global information, it will be harder to debug problems. This is because the scope of a global variable is everywhere. It can be accessed and modified from anywhere. It’s tempting to use global variables in places that you don’t want them used. But because they’re global, you have no way to restrict them.
Some languages might give you extra ways to handle this. For example in C#, instead of making the instance method public, maybe you would be better to make it internal. This will limit the access to your singleton to just that one assembly. It’s still global within that assembly.
Anything you can do to limit scope will almost always be a good thing. This is one of the few statements that I’m tempted to say always applies. Limit scope as much as possible. But I’ll stop just short of making this a rule because there’s almost always exceptions. See, I even left room for an exception in the exceptions.
I’ll end this episode with a warning. The singleton pattern is easy to implement and seems like it gives you some great results. Just use it sparingly. That global access can really cause problems in a large project.