Global variables represent an implicit hidden dependency.
As such they add complexity everywhere you use them. Do it poorly at your own peril.
Didn't know the locator pattern before. Sounds like a nice idea although... in itself it needs a global variable . Or be implemented as a singleton. But hey, can't we just implement CRender, CClient and CPhysics as singletons in the first place? Instead of declaring them global why not just have them declared in their respective files?
A singleton means "There can only be one, ever, and it is absolutely mandated and enforced".
A global variable means a shared, well-known instance, but you can still create more if you want.
Don't confuse the two.Singleton is an anti pattern. Don't do it. Generally don't talk about it except to tell people not to do it.
Someone mentions "singleton" and a massive flame war erupts about if they are pure evil, a minor evil, and if maybe some case might be an acceptable evil. Lets not do that.
For your examples, a singleton renderer breaks all kinds of visual effects, breaks several kinds of features like potentially picture-in-picture or certain multi-pass effects or cases where you want a second rendering for your own purposes. A singleton client means you cannot have a second client for any reason, not even as an AI player or a network player or as a stand-in for testing. A physics singleton means you cannot run a separate private physics simulation on any tiny thing for any reason.When you write a singleton you are almost certainly doing something wrong.
Usually you just want a well-known instance.
Logging is oft-cited as a candidate for a singleton; it should instead be a well-known instance since making it a singleton means I cannot create my own private logging functionality for a class or object instance. Application variables like command line parameters and directory paths and such is sometimes cited as a singleton, but that prohibits me from making my own version for any other purpose, such as custom tools that use the engine, so a well-known instance is preferred. Even a "service locator" system that finds the well-known instance should not be a singleton since it limits me from making my own if I need it; use a global variable, not a singleton, so I can create another if I need it.
If a game is carefully designed and rules are followed, you can have global objects that work okay. By themselves they are not necessarily fatal to the implementation.
If you do decide to share things through globals, you must be absolutely strict about what systems can modify it, when they can modify it, and about what systems can read from it an when reading is prohibited.
Failure to enforce strict controls on global variables leads to all kinds of incredibly nasty bugs, which is why they are called "evil" and should generally be avoided.
Edited by frob, 05 April 2014 - 09:43 PM.