57
\$\begingroup\$

I use cocos2d-x game engine for creating games. The engine already uses many singletons. If someone used it, then they should be familiar with some of them:

Director
SimpleAudioEngine
SpriteFrameCache
TextureCache
EventDispatcher (was)
ArmatureDataManager
FileUtils
UserDefault

and many more with overall about 16 classes. You can find a similar list on this page: Singleton objects in Cocos2d-html5 v3.0 But when I want to write I game I need much more singletons:

PlayerData (score, lives, ...)
PlayerProgress (passed levels, stars)
LevelData (parameters per levels and level packs)
SocialConnection (Facebook and Twitter login, share, friend list, ...)
GameData (you may obtain some data from server to configure the game)
IAP (for in purchases)
Ads (for showing ads)
Analytics (for collecting some analytics)
EntityComponentSystemManager (mananges entity creation and manipulation)
Box2dManager (manages the physics world)
.....

Why I think they should be singletons? Because I will need them in very different places in my game, and shared access would be very handy. In other words, I don't what to create them somewhere and pass pointers down to my all architecture as it will be very difficult. Also these are kind of things I need only one. In any case I will need several, I can use a Multiton pattern too. But the worst thing is that Singleton is the most heavily criticized pattern because of:

 - bad testability
 - no inheritance available
 - no lifetime control
 - no explicit dependency chain
 - global access (the same as global variables, actually)
 - ....

You can find some thoughts here: https://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons and https://stackoverflow.com/questions/4074154/when-should-the-singleton-pattern-not-be-used-besides-the-obvious

So, I think, I am doing something wrong. I think my code smells. :) I wounder how more experienced game developers solve this architectural problem? I want to check, maybe it is still normal in game development to have more than 30 singletons, considered the ones that are already in game engine.

I have thought to use a Singleton-Facade which will have instances of all these classes I need, but each of them would not be singletons already. This will eliminate a lots of problems, and I would have only one singleton which would be the Facade itself. But in this case I will have another design problem. The Facade will become a GOD OBJECT. I think this smells too. So I can't find a good design solution for this situation. Please advice.

\$\endgroup\$
3
  • 26
    \$\begingroup\$ Most people arguing against Singleton don't seem to realize that the work required to propagate some data/functionality through all the code might be waaay more a bug source than to use a Singleton. So basically they're not comparing, just rejecting ==> i suspect anti-Singletonism to be a Posture :-) So well, Singleton have flaws, so if you can avoid it, do it so you avoid the issues that comes with it, now if you can't, go for it without a look back. After all, Cocos2d seems to work quite fine with its 16 Singletons... \$\endgroup\$ Sep 30, 2014 at 12:33
  • 6
    \$\begingroup\$ As a reminder, this is a question about how to perform a particular task. This is not a question asking for a pro/con discussion of singletons (which would be off-topic here anyway). Further, remember that comments should be used to request clarification from the asker, not as a platform for a tangential discussion about the pros and cons of singletons. If you want to provide your input, the proper way to do so is to provide a legitimate answer to the question, in which you can temper your solution with advice for or against the singleton pattern. \$\endgroup\$
    – user1430
    Oct 1, 2014 at 15:53
  • \$\begingroup\$ I assume that these singletons are then globally accessible? Which would be one reason to avoid that pattern. \$\endgroup\$ Oct 2, 2014 at 11:07

8 Answers 8

42
\$\begingroup\$

I initialize my services in my main application class and then pass them as pointers to whatever needs to use them either through the constructors or functions. This is useful for two reasons.

One, the order of initialization and cleanup is simple and clear. There is no way to accidentally initialize one service somewhere else like you can with a singleton.

Two, it's clear who depends on what. I can easily see what classes need what services just from the class declaration.

You may think it's annoying to pass all these objects around, but if the system is designed well, it's really not bad at all and makes things much clearer (for me anyway).

\$\endgroup\$
8
  • 35
    \$\begingroup\$ +1. Further, the "annoyance" of having to pass references to systems around helps to counteract dependency creep; if you have to pass something to "everything," that's a good sign that you have a bad coupling problem in your design, and it's much more explicit this way than with promiscuous global access to everything from everywhere. \$\endgroup\$
    – user1430
    Sep 30, 2014 at 15:59
  • 2
    \$\begingroup\$ This doesn't actually provide a solution ... so you have your program class with a bunch of singleton objects in it and now 10 levels deep in code somehting in the scene needs one of those singletons ... how is it passed in? \$\endgroup\$
    – War
    Oct 1, 2014 at 17:05
  • \$\begingroup\$ Wardy: Why would they need to be singletons? Sure, mostly you might be passing around a particular instance, but what makes a singleton a singleton is that you CANNOT use a different instance. With injection, you can pass one instance for one object and another for the next. Just because you don't end up doing that for whatever reason, doesn't mean you couldn't. \$\endgroup\$
    – parar
    Oct 1, 2014 at 18:09
  • 3
    \$\begingroup\$ They aren't singletons. They are regular objects like anything else with a well defined owner that controls init/cleanup. If you are 10 levels deep with no access, maybe you have a design issue. Not everything needs or should have access to renderers, audio, and such. This way makes you think about your design. As an added bonus for those who test their code (what??), unit testing also becomes much easier. \$\endgroup\$
    – megadan
    Oct 1, 2014 at 18:36
  • 2
    \$\begingroup\$ Yes, I think dependency injection (with or without a framework like Spring) is a perfect solution for handling this. I found this to be a great article for those wondering how to better structure code to avoid passing things everywhere: misko.hevery.com/2008/10/21/… \$\endgroup\$
    – megadan
    Oct 2, 2014 at 17:43
19
\$\begingroup\$

I won't discuss about the evilness behind singletons because Internet can do that better than me.

In my games I use the Service Locator pattern to avoid having tons of Singletons/Managers.

The concept is pretty simple. You only have one Singleton that acts like the only interface to reach what you used to use as Singleton. Instead of having several Singleton you now have only one.

Calls like :

FlyingToasterManager.GetInstance().Toast();
SmokeAlarmManager.GetInstance().Start();

Looks like this, using the Service Locator pattern:

SvcLocator.FlyingToaster.Toast();
SvcLocator.SmokeAlarm.Start();

As you can see every Singleton is contained in the Service Locator.

To have a more detailed explanation I suggest you to read this page about how to use the Locator Pattern.

[EDIT] : as pointed in comments, the site gameprogrammingpatterns.com also contains a very interesting section on Singleton.

I hope it helps.

\$\endgroup\$
11
  • 4
    \$\begingroup\$ The site linked to here, gameprogrammingpatterns.com, also has a chapter on Singletons that seems relevant. \$\endgroup\$
    – ajp15243
    Sep 30, 2014 at 13:55
  • 30
    \$\begingroup\$ Service locators are just singletons that move all the normal problems to runtime rather than compiletime. However, what you're suggesting is just a giant static registry, which is almost better, but still essentially a mass of global variables. This is simply a matter of bad architecture if many levels need access to the same objects. Proper dependency injection is what is needed here, not differently named globals than the current globals. \$\endgroup\$
    – Magus
    Sep 30, 2014 at 14:54
  • 2
    \$\begingroup\$ Can you elaborate on "proper dependency injection"? \$\endgroup\$ Sep 30, 2014 at 15:03
  • 18
    \$\begingroup\$ This doesn't really help the issue. It's essentially lots of singletons merged into one giant singleton. None of the underlying structural issues are fixed or even addressed, the code still stinks its just prettier now. \$\endgroup\$ Sep 30, 2014 at 15:29
  • 4
    \$\begingroup\$ @classicthunder While this doesn't address every single issue, this is a big improvement over Singletons because it does address several. In particular, the code you write is no longer coupled to a single class, but rather an interface/category of classes. Now you can easily swap different implementations of the various services. \$\endgroup\$
    – jhocking
    Sep 30, 2014 at 15:49
13
\$\begingroup\$

Reading all these answers, comments and articles pointed out, especially these two brilliant articles,

eventually, I have come to the following conclusion, which is kind of an answer to my own question. The best approach is not to be lazy and pass dependencies directly. This is explicit, testable, there is no global access, can indicate wrong design if you have to pass delegates very deep and in many places and so on. But in programming one size does not fit all. Thus, there are still cases that it is not handy to pass them directly. For example in case we create a game framework (a code template which will be re-used as a base code to develop different kinds of games), and include there lots of services. Here we don't know how deep each service can be passed, and how many places it will be necessary. It dependents on a particular game. So what do we do in this kind of cases? We use Service Locator design pattern instead of Singleton, which is actually the same Singleton, with the following very important improvements:

  1. You don't program to the implementations but to the interfaces. This is very essential in terms of OOP principals. At runtime you can change or even disable the service using Null Object pattern. This is not only important in terms of flexibility, but it directly helps in testing. You can disable, mock, also you can use Decorator pattern, to add some logging and other functionality as well. This is very important property, which Singleton does not have.
  2. Another huge advantage is that you can control the lifetime of the object. In Singleton you only control the time the object will be spawned by Lazy Initialization pattern. But once the object is spawned, it will live until the end of the program. But in some cases you would like to change the service. Or even shut it down. Especially in gaming this flexibility is very important.
  3. It combines/wraps several Singletons into one compact API. I think you may also use some Facade like Service Locators, which for a single operation might use several services at once.
  4. You may argue that we still have the global access which is the main design problem with the Singleton. I agree, but we will need this pattern only and only if we want some global access. We should not complain about global access, if we think that direct dependency injection is not handy for our situation, and we need a global access. But even for this problem, an improvement is available (see the second article above). You can make all the services private, and you can inherit from Service Locator class all the classes you think they should use the services. This can significantly narrow the access. And please consider that in case of Singleton you cannot use inheritance because of the private constructor.

Also we should consider that this pattern was used in Unity, LibGDX, XNA. This is not an advantage, but this is kind of a proof of the usability of the pattern. Consider that these engines were developed by lots of smart developers a long time and during the evolution phases of the engine they still didn't find any better solution.

In conclusion, I think Service Locator can be very useful for the scenarios described in my question, but still should be avoided if it is possible. As a rule of thumb - use it if you have to.

EDIT: After a year of work and using direct DI and having problems with huge constructors and lots of delegations, I have done more research and have found a good article that talks about pros and cons about DI and Service Locator methods. Citing this article (http://www.martinfowler.com/articles/injection.html) by Martin Fowler that explains when actually Service locators are bad:

So the primary issue is for people who are writing code that expects to be used in applications outside of the control of the writer. In these cases even a minimal assumption about a Service Locator is a problem.

But anyways, if you want to us DI first time, you should read this http://misko.hevery.com/2008/10/21/dependency-injection-myth-reference-passing/ article (pointed out by @megadan), by paying very careful attention to the Law of Demeter (LoD) or principle of least knowledge.

\$\endgroup\$
1
  • \$\begingroup\$ My personal intolerance toward service locators rises mainly from my attempts to test code which uses them. In the interest of black-box testing, you call the constructor to make an instance to test. An exception may be thrown immediately, or on any method call, and there may be no public properties to lead you to the missing dependencies. This may be minor if you have access to the source, yet it still violates the Principle of Least Surprise (a frequent problem with Singletons). You have suggested passing in the service locator, which alleviates part of this, and are to be commended for it. \$\endgroup\$
    – Magus
    Oct 1, 2014 at 19:08
3
\$\begingroup\$

It isn't uncommon for parts of a code base to be considered cornerstone objects or a foundation class, but that doesn't justify it's life cycle to be dictated as a Singleton.

Programmers often rely on the Singleton pattern as a means of convenience and pure laziness rather than taking the alternate approach and being a tad more verbose and imposing object relationships between one another in an explicit manor.

So ask yourself which is easier to maintain.

If you're like me, I prefer to be able to open a header file and briefly skim over constructor arguments and public methods to see what dependencies an object requires rather than having to inspect hundreds of lines of code in an implementation file.

If you had made an object a Singleton and later realize you need to be capable of supporting multiple instances of said object, imagine the sweeping changes needed if this class was something you used pretty heavily throughout your code base. The better alternative is to make dependencies explicit, even if the object is only allocated once and if the need arises to support multiple instances, you can safely do so without such concerns.

As others have pointed out, use of the Singleton pattern also obfuscates coupling that often signifies poor design and high cohesion between modules. Such cohesion is usually undesirable and leads to brittle code that can be hard to maintain.

\$\endgroup\$
1
  • \$\begingroup\$ -1: This answer wrongly describes the singleton pattern, and all its arguments describe the problems with poor implementation of the pattern. Proper singleton is an interface, and it avoids every single problem you described (including the shift to non-singleness, which is a scenario that GoF addresses explicitly). If it is difficult to refactor the use of a singleton, then refactoring the use of an explicit object reference can only be more difficult, not less. If singleton somehow causes MORE code coupling, it simply was done wrong. \$\endgroup\$ Oct 1, 2014 at 15:41
1
\$\begingroup\$

Singleton is a famous pattern, but it's good to know the purposes it serves, and its pros and cons.

It really makes sense if there is no relationship at all.
If you can handle your component with a totally different object (no strong dependency) and expect having the same behavior, the singleton may be a good choice.

On the other hand, if you need a small functionality, only used at certain times, you should prefer passing references.

As you mentioned, singletons have no lifetime control. But the advantage is they have a lazy initialization.
If you don't call that singleton in your application lifetime, it will not be instantiated. But I doubt you build singletons and not use them.

You must see a singleton like a service instead of a component.

Singletons works, they never broke any application. But their lacks (the four you've given) are reasons you won't make one.

\$\endgroup\$
1
\$\begingroup\$

The engine already uses many singletons. If someone used it, then they should be familiar with some of them:

Unfamiliarity isn't the reason why singletons need to be avoided.

There are many good reasons why Singleton is necessary or unavoidable. Game frameworks often uses singletons because it is an unavoidable consequence of of having just a single stateful hardware. It makes no sense to ever want to control these hardwares with multiple instances of their respective handlers. The graphic surface is an external stateful hardware and accidentally initializing a second copy of the graphic subsystem is nothing short of disastrous, as now the two graphic subsystem will be fighting each other over who gets to draw and when, overwriting each other uncontrollably. Likewise with event queue system, they will be fighting over who gets the mouse events in nondeterministic fashion. When dealing with a stateful external hardware in which there is only one of them, singleton is unavoidable to prevent conflicts.

Another place where Singleton is sensible is with Cache managers. Caches are a special case. They should not really be considered a Singleton, even when they use all the same techniques as Singletons to stay alive and live forever. Caching services are transparent service, they aren't supposed to alter the behaviour of the program, so if you replace the cache service with a null cache, the program should still work, except that it only runs slower. The main reason why cache managers are exception to singleton though is because it doesn't make sense to shut down a cache service prior to shutting down the application itself because that will also discard the cached objects, which defeats the point of having it as a singleton.

Those are good reasons why these services are singletons. However, none of the good reasons to have singletons apply to the classes you have listed.

Because I will need them in very different places in my game, and shared access would be very handy.

Those aren't reasons for singletons. Those are reasons for globals. It is also a sign of poor design if you need to pass a lot of things around various systems. Having to pass things around indicates high coupling which can be prevented by good OO design.

Just from looking at the list of classes in your post that you think need to be Singletons, I can say that half of them really shouldn't be singletons and the other half seems like they shouldn't even be there in the first place. That you need to pass objects around seems to be due to the lack of proper encapsulation rather than actual good use cases for singletons.

Let's look at your classes bit by bit:


PlayerData (score, lives, ...)
LevelData (parameters per levels and level packs)
GameData (you may obtain some data from server to configure the game)

Just from the classes names, I would say that these classes smells like Anemic Domain Model antipattern. Anemic objects usually results in a lot of data that need to be passed around which increases coupling and makes the rest of the code cumbersome. Also, anemic class hides the fact that you are probably still thinking procedurally rather than using object orientation to encapsulate details.


IAP (for in purchases)
Ads (for showing ads)

Why do these classes need to be singletons? It seems to me that these should be short-lived classes, which should be brought up when they are needed and deconstructed when the user finishes the purchase or when the ads no longer need to be shown.


EntityComponentSystemManager (mananges entity creation and manipulation)

In other words, a constructor and a service layer? Why is this class with no clear boundaries nor purpose even there in the first place?


PlayerProgress (passed levels, stars)

Why is the player progress separate from the Player class? The Player class should know how to keep track of its own progress, if you want to implement progress tracking in a different class than the Player class for separation of responsibility, then PlayerProgress should be behind Player.


Box2dManager (manages the physics world)

I can't really comment any further on this one without knowing what this class actually does, but one thing is clear is that this class is poorly named.


Analytics (for collecting some analytics)
SocialConnection (Facebook and Twitter login, share, friend list, ...)

This seem to be the only classes where Singleton may be reasonable, because the social connection objects are not actually your objects. The social connections are just a shadow of external objects that lives in a remote service. In other word, this is a kind of cache. Just make sure you clearly separate the caching part with the service part of the external service, because the latter part shouldn't need to be a singleton.

One way you can avoid passing instances of these classes around is by using message passing. Rather than making a direct call to instances of these classes, instead you send a message addressed to the Analytic and SocialConnection service asynchronously, and these services are subscribed to receive these messages and act on the message. Since the event queue is already a singleton, by trampolining the call, you avoid the need to pass an actual instance when communicating with a singleton.

\$\endgroup\$
1
  • \$\begingroup\$ The lifetime and unicity of your services can perfectly be controlled though configuration rather than through singletons. And you can have additional or alternate graphics surfaces that actually renders to texture or to a mock object, the latter being invaluable for tests. Likewise with the event queue, there are applications for supporting alternate or concurrent implementations, and here the test applications are even more obvious especially if you dabble in ML-assisted testing. \$\endgroup\$ Jun 14 at 12:58
-1
\$\begingroup\$

Singletons to me are ALWAYS bad.

In my architecture I created a GameServices collection that the game class manages. I can search add to and remove from this collection as required.

By saying something is in global scope you are basically saying "this hting is god and has no master" in the examples you provide above I would say most of those are either helper classes or GameServices in which case the game would be responsible for them.

But that's just my design in my engine, your situation may be different.

Putting it more directly ... The only real singleton is the game as it owns every part of the code.

This is answer is based on the subjective nature of the question and is based purely on my opinion, it may not be correct for all developers out there.

Edit: As requested ...

Ok this is from my head as I don't have my code in front of me at the moment but essentially at the root of any game is the Game class which is truely a singleton ... it has to be!

So I added the following ...

class Game
{
   IList<GameService> Services;

   public T GetService<T>() where T : GameService
   {
       return Services.FirstOrDefatult(s => s is T);
   }
}

Now I also have a system class (static) that contains all my singletons from the entire program (contains very little, game and config options and thats about it) ...

public static class Sys
{
    // only the main game assembly can set this (done by the game ctor)
    // anything can get
    public static Game Game { get; internal set; }
}

And usage ...

From anywhere I can do something like

var tService = Sys.Game.getService<T>();
tService.Something();

This approach means that my game "Owns" stuff that would typically be considered a "singleton" and I can extend the base GameService class however I want. I have interfaces like IUpdateable that my game checks for and calls in to any services that implement it as needed for specific situations.

I also have services that inherit / extend other services for more specific scene scenarios.

For example ...

I have a Physics service that handles my physics simulations but depending on the scene physics simulation may need some slightly different behaviour.

\$\endgroup\$
13
  • 1
    \$\begingroup\$ Shouldn't the game services be instantiated only once ? If so, it's just a singleton pattern not enforced at the class level, which is worst than a properly implemented singleton. \$\endgroup\$ Sep 30, 2014 at 12:43
  • 2
    \$\begingroup\$ @Wardy I don't clearly understand what you have done but it sounds like the Singleton-Facade I have described and it should become a GOD object, right? \$\endgroup\$
    – Narek
    Sep 30, 2014 at 12:47
  • 10
    \$\begingroup\$ It's just a Singleton pattern implemented at the game level. So basically its most interesting aspect is to allow you to pretend you're not using Singleton. Useful if your boss is from the anti-pattern church. \$\endgroup\$ Sep 30, 2014 at 12:53
  • 2
    \$\begingroup\$ I'm not sure how this is effectively different from using Singletons. Isn't the only difference in how specifically you access your single existing service of this type? I.e. var tService = Sys.Game.getService<T>(); tService.Something(); instead of skipping the getService part and accessing it directly? \$\endgroup\$
    – Christian
    Sep 30, 2014 at 13:49
  • 1
    \$\begingroup\$ @Christian: Indeed, that is exactly what the Service Locator antipattern is. Apparently this community still thinks it is a recommended design pattern. \$\endgroup\$
    – Magus
    Sep 30, 2014 at 14:59
-1
\$\begingroup\$

An essential ingredient of singleton-elimination which opponents of singleton often fail to consider is adding extra logic to deal with the vastly more complicated state that objects encapsulate when singletons give way to instance values. Indeed, even defining the state of an object after replacing a singleton with an instance variable can be difficult, but programmers who replace singletons with instance variables should be prepared to deal with it.

Compare, for example, Java's HashMap with .NET's Dictionary. Both are quite similar, but they have a key difference: Java's HashMap is hard-coded to use equals and hashCode (it effectively uses a singleton comparator) while .NET's Dictionary can accept an instance of IEqualityComparer<T> as a constructor parameter. The run-time cost of keeping the IEqualityComparer is minimal, but the complexity that it introduces is not.

Because each Dictionary instance encapsulates an IEqualityComparer, its state is not just a mapping between the keys it actually contains and their associated values, but instead a mapping between the equivalence sets defined by the keys and the comparator and their associated values. If two instances d1 and d2 of Dictionary hold references to the same IEqualityComparer, it will be possible to produce a new instance d3 such that for any x, d3.ContainsKey(x) will equal d1.ContainsKey(x) || d2.ContainsKey(x). If, however, d1 and d2 may hold references to different arbitrary equality comparers, there will in general be no way to merge them so as to ensure that condition holds.

Adding instance variables in an effort to eliminate singletons, but failing to properly account for the possible new states that could be implied by those instance variables can create code which ends up being more brittle than it would have been with a singleton. If every object instance has a separate field, but things will malfunction badly unless they all identify the same object instance, then all the new fields have bought is an increased number of ways things can go wrong.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ While this is definitely an interesting aspect to the discussion, I don't think it actually addresses the question actually asked by the OP. \$\endgroup\$
    – user1430
    Sep 30, 2014 at 22:26
  • 1
    \$\begingroup\$ @JoshPetrie: The comments on the original post (e.g. by Magus) suggested that the runtime cost of carrying around references to avoid using singletons was not great. As such, I would consider relevant the semantic costs of having every object encapsulate references for the purpose of avoiding singletons. One should avoid singletons in cases where they can be avoided cheaply and easily, but code which doesn't overtly require a singleton but might break as soon as multiple instances of something exists is worse than code which uses a singleton. \$\endgroup\$
    – supercat
    Sep 30, 2014 at 22:46
  • 2
    \$\begingroup\$ Answers are not for addressing the comments they are for directly answering the question. \$\endgroup\$ Oct 1, 2014 at 4:23
  • \$\begingroup\$ @ClassicThunder: Do you like the edit better? \$\endgroup\$
    – supercat
    Oct 1, 2014 at 13:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .