There isn’t any one pattern fits all in programming, different designs are best for different situations. Unfortunately, the singleton pattern gets an especially bad rap from a lot of programmers. Like all design patterns, the singleton can cause problems, but I believe this is largely due to mis-use and mis-understanding of the pattern.
Management and Memory:
Singletons are great to manage several operations or objects. Using them as the ‘Manager’ or ‘Controller’ for several objects makes them great to manage memory too. They can listen for memory warnings and quickly free some of their objects when needed. Let’s say you have an ImageCache object. Since it’s in-charge of all of your Image objects it can easily manage the memory around them. If the Image object itself was listening for memory warnings, how is it to know whether or not to free itself from memory? How would different owners of different Images know that they don’t need to clear their cache because other owners took care of it? The singleton makes the executive decision. It knows how many images it has in memory, which ones were accessed more recently, and how big each of them are. It’s the boss and central authority which can allow you to tune it to meet your needs and easily debug exactly what’s happening.
Similarly, since singletons can be in charge of several operations they are great for managing synchronization, concurrency, and performance. They can appropriately adjust order and timing and you can easily find that same central authority that is making all the decisions.
Portability and Re-Use:
A good singleton should be very portable, since chances are integration with your code base is spread pretty wide. With a portable singleton you now have an entire controller that can be ported to other code and very easily re-used.
Take a game with an EnemyManager singleton. If constructed properly, you should need maybe two classes and a header file to re-use it (we are assuming a fairly simple enemy here: Enemy, EnemyManager, GameConstants.h). Now, if you made EnemyManager relatively de-coupled, but didn’t make it a singleton, you could still probably port it easily. I would argue though that a singleton is easier to integrate, especially on a global scale. Also, if the singleton handles threading itself, then it’s another headache off your plate. It takes a minimal amount of effort to re-use a singleton in other projects.
When you think of a singleton, you think of one instance, and though multiple instances technically aren’t a singleton by the definition, I would argue some classes that manage their own global state of one instance still qualify. Many classes that are ‘pseudo singletons’ can in fact have one global shared instance and several independent instances. This provides a lot of flexibility if you want to have a global variable or if you want to restrict its scope.
A good example of this is Apple’s NSUserDefaults class. NSUserDefaults has a +sharedDefaults method to access a global instance of itself, but if you need a separate instance you can create your own and pass it around.
Singleton’s make debugging a whole lot easier. If you’ve ever had a breakpoint in a class that has hundreds of instances you know the pain of trying to step through the code and figure out what object you are looking at. It usually requires modifying the code to create only one instance to step through it properly anyway. With a singleton you only have one instance, so when that breakpoint hits, you know exactly what you are looking at. Additionally, if you are trying to figure out when a property is read or modified, put a break point in the singleton and then you can easily monitor what is accessing it and from where. Lastly, with a singleton you can very easily modify states for debugging and have them take effect across the whole code base as well.
One main advantage of a singleton is global access. If not done carefully, global access will corrupt your code base, but if you do it right it can make management so much easier. Rather than having to pass an object around from class to class you can very easily access and modify its state by asking it for itself. Anywhere in your code you can ask the GameManager if it’s paused, rather than having to give everybody their own pointer to a GameManager.
Lots of Mutability:
With great power comes great responsibility. A singleton with too much mutability can really make things messy quickly. You shouldn’t be modifying a singleton’s state too frequently, and certainly not in too many places. A good example is a login screen. When the user logs in you could set LoginManager’s currentUser, and then set it again when a log out occurs. While you will likely access currentUser in several places, you are only modifying its state in two places, and only after the user takes a specific action that will likely only occur once per session. A bad example would be an asynchronous NetworkController who’s network operations toggle a isWorking boolean on it. Since these operations have no knowledge of one another they shouldn’t be changing this state. Just because one network operation finished doesn’t mean others aren’t working.
Too Easy To Access:
Since singletons are really easy to access on a global scale it can be easy to muddy up your code base. You should be thoughtful when accessing or modifying a singleton’s state. Just because you have this great and easy to use tool doesn’t mean you can be careless with it. Modifying a singleton’s state carelessly will leave you extremely frustrated when you are trying to debug your code.
The delegate pattern doesn’t work well with singletons. In certain languages you can do some tricky things related to memory management and multiple delegates, but really what you are doing is adding observers. Having a single delegate doesn’t work with singleton’s because you will likely have multiple things setting it.
Singleton’s are inherently bad at scalability. Unless you create the ‘pseudo singleton’ I mentioned above, if you need multiple instances of your singleton you are stuck. The key is to avoid making things singletons if you believe you will likely need multiple instances.
While singletons are good for injecting test data, they can be frustrating with unit tests. Singletons can’t be broken into smaller scopes for unit testing, so all your unit tests affect one another, pretty much making any test useless.
There is this common myth that singletons create tightly coupled code. Guess what? Anytime you need to access a class from another class you are coupling those classes together, regardless if they are singletons or not. Now, of course, some will probably argue It’s easier to create a singleton with a lot of dependencies since it’s accessed across the code base, but I would actually say with a singleton it’s easier to avoid. Why you ask? If you know a class is a singleton then you know not to have it dependent on other classes (at least as much as possible), where as if it’s just another class it’s easier to overlook what dependencies you are putting into it.
A singleton with lots of dependencies is a bad singleton, and will create a lot of ugly and tightly coupled code. Singleton’s should be very loosely coupled to other classes internally so they are lightweight and portable. That way if you do have classes that touch your singleton, it’s very easy to bring it along with them for re-use.
Saying that singletons are bad for concurrency is a bunch of hogwash. They are in fact often really good approaches to managing multi-threaded processes. The argument goes that with singletons you are accessing the same space in memory across threads and you may get deadlocks and synchronization bugs as a result. This argument is naive. With any class you can get yourself into a world of trouble with concurrency, regardless if it’s a singleton.
Sure you can certainly have a singleton access shared memory across threads, but you can also synchronize that access with a singleton extremely easily. Additionally, you could duplicate the memory for a thread specific scope, and what better way to manage it than a singleton. This actually makes threading easier since your code can just call the singleton and it will handle the synchronization and/or concurrency automatically.
Well we can’t talk about singletons without talking about logging. Everyone jumps to this as the ‘ideal’ singleton and then the naysayers mention how their project has several loggers. A common argument that logging isn’t suitable for a singleton is that your log file or console can quickly become bloated and you cannot isolate logging to specific areas. Well as Captain O’Hagan from Super Troopers said best “[irish accent] I’ll believe ya when me shit turns purple and smells like rainbow sherbet.” It’s very simple to have a singleton that has several different logging capabilities, be it by type, thread, or scope. In fact, if a singleton manages the various logging sectors it can also globally and easily manage whether or not they are enabled. Take these implementations in Objective-C as an example:
[[Logger sharedLogger] logEvent:(NSString *)event withType:(LogType)type]
[[[Logger sharedLogger] loggerWithID:(NSString *)loggerID] logEvent:(NSString *)event]
[[Logger loggerForThread] logEvent:(NSString *)event]
Very easily you can segment and control your logging while using one instance to achieve it and have global access across your code base.
People often argue that lazy loading of singletons can create performance problems because you don’t know when the object will be instantiated. I have a couple of problems with this thought process. The first is that if you didn’t have a singleton, you would likely have to instantiate the class when you wanted to use it, and even though you know when it’s created, you are consuming unnecessary CPU cycles. In the right situations a singleton is more efficient because the creation only happens once.
The second problem I have is that if you want to know when a singleton will be created, ensure that your code is structured as such. Load the singleton at app launch or during a game loading screen. Lastly, why the hell is your singleton doing a bunch of heavy operations when it’s created? And If you really do need to do some heavy lifting why isn’t it asynchronous?
When to use a singleton?
It is important to ask yourself a few key questions when deciding whether or not a singleton pattern is the right one.
- Is your class suited to (generally) have only one instance?
- Does your class need to be shared across your code heavily?
- Does your class need to control several objects and/or processes?
- Does your class require synchronization? (Such as writing to a database)
- Is your class fairly immutable? Will you being modifying its state minimally?
If you answered yes to most of these, a singleton may be the right choice for your class.
A few good examples of singletons are:
NetworkController – Easy to manage multiple asynchronous network requests and allows any class to quickly integrate with networking.
LocalStore – Most databases need synchronization when writing and reading. Having a single instance to manage your single store makes this a breeze.
ImageCache – As I mentioned above, having one instance managing your entire image memory footprint prevents duplicates and allows for better optimization.
LoadingIndicator – For iOS I like to use a pattern of showInView: and hideFromView:. This allows multiple loading indicators to co-exist based on their view, but integration to show a loading indicator is minimal since they are managed by the singleton.
GameManager / Application – Chances are you have your game or app. Chances are there is only one of them. Chances are it will run itself once within its own scope. A singleton is perfect to manage this since the one instance of your code should be managed by one instance.
ConfigController – You may have multiple configurations that need loading depending on what you are doing. For simple apps though, a single ConfigController usually suffices, and then your code can ask it for configurable states easily. Additionally, you can easily modify this state for debugging.
AdController – Again, different circumstances may require different designs here. But if your app is just showing some simple ads, chances are you want to get them from one manager.
Analytics – In general Analytics are used to track user sessions. Since there is likely only one user, on one device, in one instance of your code, having a singleton for analytics makes perfect sense. Additionally, analytics usually write to a store and use networking, with a singleton you can ensure this process all happens under one roof.
PurchaseManager – Items are either purchased or they aren’t. Having a singleton purchase manager can easily allow different parts of your code to check the purchased state. Also, a user probably isn’t purchasing things too quickly so modifying state should be minimal.
ConnectivityController – A device is either connected to the internet or it isn’t. No reason to have multiple controllers checking the same state. With a singleton monitoring connectivity, your entire code base can quickly check its status.
VersionController – Your product has a version. When running, just one version is running. A singleton that can both check for updates and give global access to the version is handy. You only need one of them and they are immutable, perfect for a singleton.
I’ve written a lot of software, with a lot of it doing very different things. Without even looking at my previous projects I can pretty much guarantee every single one of them has at least one singleton class. The singleton is a great design pattern when used properly, and no matter how many programmers dance to the tune of “singletons are evil”, I will continue to use them and advocate for them. I’ve searched high and low, have had debate after debate, but am still waiting for someone to convince me singletons should be avoided.