Disch, you're tempting me to actually go OO with this :P As mentioned, I've a suspicion that I'll need a number of them later on, and it would indeed solve it nicely. |
The only downside is that you'll have to pass around an RNG object instead of referring to a global instance of one.
I am not a fan of globals.
Disch, do you think that the OO way would still be useful in cases where only one instance is guaranteed to be needed? As in my second (artificial) example, for instance. |
Singletons are weird because they're sort like fake-OO. There isn't really any difference between a singleton and a series of global functions inside a namespace.... so your two examples seem equivalent to me.
The question I always ask before using a singleton (or globals) is "am I sure that I will only ever want one of this object? No matter the circumstances?".
The answer to that question is
usually almost always "no". Even for something like a 'Game' object which runs the overall game logic flow --- I can conceive of situations where more than one of them might be useful:
- I used to be in the retro emulation scene, and people would make emulators that would run several different games in parallel. This is easily accomplished with OOP design -- just make a new Emu object. But if you use globally driven logic, you're hosed.
- I don't know if you've ever played games like Braid or Prince of Persia: Sands of Time. One of the gimmicks in those games is the ability to rewind time. One way this can be accomplished is by making "movies" which can playback user input. Run that user input through a deterministic world and you'll get the same output. Rewinding is then just generating that movie and playing it in reverse. To make that easier, you could have multiple 'Game' objects running different parts of the movie at the same time.
About the only time I thought I
really would only ever want 1 of something is for things like a resource manager... where you have read-only resources that are loaded from a file or something. Where there is literally
zero value in having the same resources loaded multiple times in memory, regardless of how many games/objects are accessing it.
But even with that.... you can run into multithreading issues.
But it'd be very easy to argue that I'm planning ahead for too much. Most games don't need multiple 'Game' objects. Most games don't need multiple resource managers. And in those cases... a global/singleton is "good enough". It gets the job done and is easy to implement.
It's just... my personal preference is to avoid them. Sure, I may not
need all the flexibility that unique objects provide... but it isn't really hard to use them. And if I ever
do need them, then I have them.