The Singleton design pattern is an area of C++ philosophy where I happen to be in complete disagreement with the rest of the C++ world.  Singleton classes, as described in Gamma Et Al. are unnecessary; they add excess verbiage to code, and they are a symptom of bad design. I have described my reasons for saying this in my writeup called Don't Use Singleton Classes.

My challenge to you, the reader: describe for me a class that must be implemented using the form of the Singleton Pattern in Gamma Et Al.. Alternatively, describe one that is simpler, or works more efficiently, using that pattern. Put writeups to answer the challenge in this node and I will do my best to answer them. Let me know you did with a /msg.

You're going to have to work really hard to convince me that any singular object should have its behavior and singularity merged into a singleton class.

Suggested further reading: Arthur J. Riel, Object-Oriented Design Heuristics, 1996, Addison-Wesley, ISBN 0-201-63385-X.

I agree with Core's comments (Although I wish they'd been in the other node) for every OO language except C++. In C++ you can declare any global variable you want, exactly the way you do in C. You make things like singletons to enforce their working correctly. In C, you're working without a net.

I must challenge several points put forward by Rose Thorn:

  1. The number of classes in your program does not determine maintenance burden all by itself. Remember that small classes are easier to maintain. A singleton class that has two members for each function (one for the actual behavior and one to forward to the singular instance) is twice as complex as the server class or the client class separately. Regardless of whether we separate the client and server or merge them, we have the same amount of code to maintain!

  2. The client class is the real thing; it's the class the outside world uses. Suppose that not all of your class's behavior is singular. Where do you put the non-singular behavior? In the client class of course.

  3. Separation between the domain model and the implementation model is a Good Thing, not a Bad Thing. If by "re-engineering" you mean supplying a different implmentation, all you have to do is implement the server class interface to perform the behavior the client class expects. This is easier when you have separate classes. If you want to change the interface, you need to change both members under any model.

  4. Polymorphism is not the be-all and end-all of Object-Oriented Programming. Many C++ gurus will tell you that encapsulation is far more important. Encapsulation is about presenting an interface to the world, a contract between the class designer and the class user. If the contract can be satisfied without polymorphism, polymorphic member functions need not apply. Remember that Bjarne Stroustrup's original version of C with Classes, which made OOP something more than an academic toy, did not allow for polymorphism. Virtual functions were added later.

  5. I'd like to see a real model of a polymorphic class where every object must have its own behavior. For our theoretical Person class, we must be talking about an abstract base class Person from which a Joe class, a Jim class, and a MarySue class inherit. We want to pass Person objects into some other function somewhere, otherwise the Person class is meaningless. Joe has a magnetic personality, and along comes his disciple Bob, who acts exactly like Joe. All of a sudden, our assumption that there can be only one Joe is gone.

    (As an aside, It could be argued that a person's behavior is determined by our internal state, which comes from our initial genetic material [constructor arguments] plus outside environmental influences [mutator functions, input and output]. The internal processes that turn state into behavior (chemistry) remain the same.)

    For a different example, suppose that Ford and GM have quite different accounting practices. In an accounting application, we can model this with a FordAccountingSystem class and a GeneralMotorsAccountingSystem class. But, suppose Ford hired GM's CFO away form them. The new CFO replaces Ford's accounting system with an exact duplicate of GM's. We might be able to model Ford's new accounting system with a copy of General Motors's accounting system, except that we're that with the same AccountingSystem class as before. But if it's a singleton, we're stuck with separating the interface from the implementation again. The problem lies in having a GeneralMotorsAccountingSystem class rather than a SpiffyNewAccountingSystem class which can be applied to both Ford and GM.