A singleton is a way of designing a part of an object-oriented system that was used frequently enough to deserve its own name: the Singleton Design Pattern. In practice, a singleton is a class which can only have one instance at any given time, and for which that unique instance is globally accessible.
The purpose of a singleton class is to represent a concept which, by its own fundamental nature, can only exist as a single instance. Sometimes, this happens because there are no technical solutions available to allow more than one instance of that concept, or sometimes because the solutions do exist but are too impractical or difficult to implement.
To determine the need for the Singleton Design Pattern in a practical case, one should then examine the following checklist:
- Is there a need for the considered functionality to be grouped in an object?A valid reason for wishing to regroup the functionality as a single object is if you need to manipulate it as an object, for instance to implement an interface and use functions or methods that can be applied to that interface. Another valid reason is the existence of several values related to that functionality which should then be grouped as a single object.If there is no reason to group the functionality in an object (no values to represent state, no usage as an object implementing an interface), then it is preferable to use a function, method, or namespace instead.
- Is there a need for the considered functionality to be grouped in a class?The alternative here is often initializing a global instance of an existing class to represent the functionality, instead of defining a brand new class for that purpose. For instance, even though the standard output of a program is by definition a one-instance-only concept, many implementations of the C++ std::cout are not singletons, but rather global variables initialized with a specific internal buffer that prints to the standard output (that buffer, in turn, is not a singleton because it provides no global access to its unique instance).If the difference in functionality is so wide that you would have to rewrite most of the class, then it is a good idea to create a brand new class. By contrast, if the difference is very small, then one can often get away with using an old class instead.
- Is there a technical reason for which the considered functionality does not allow multiple instances of the class?If it is technically possible to create several instances of the class, then the use of a singleton is not warranted: one can simply create a global instance instead.Note that it is not enough to decide that more than one instance will not be needed to warrant the use of a singleton! The reason the singleton is used is because the represented concept itself, independently of any external reasons such as how it will be used by the program, does not allow the creation of multiple instances. If the program happens to only create a single instance, then this is a coincidence and not a technical limitation.
Note that this is only an argument against preventing the creation of multiple instances: the other traits of the singleton pattern (being a class which has a globally accessible instance) are not necessarily discarded if this particular condition does not hold.
- Is there a need for the unique instance to be globally accessible?The non-singleton alternative is the one used by std::cout : implement a singleton-like class (only allows a single instance) but use its unique instance locally to either initialize a global instance of another class or as a persistent local variable in a function or method.The question to be asked here is whether an observer outside the scope of the module or function you are working in needs to know of the existence of the singleton candidate, or whether the fact that the class extends a public interface is enough.
If knowledge of the class’ existence is necessary, then a globally accessible instance is almost always warranted: there is no point in knowing about the class if one cannot access its instance, and there is no point in passing the instance of that class around while knowing it is the only one.
On the contrary, if only the interface is public, then only the module which contains the class needs to know about the class (and provide it to the outside world as that interface).
This is an argument against making the instance a global variable: the other traits of the singleton pattern (the limitation to a single instance, for instance) still hold even if the instance itself is not global.
If the candidate satisfies the above four conditions, then it can accurately be described by the Singleton Design Pattern.
Monostates
The Monostate Design Pattern is a close relative to the Singleton Design Pattern, in terms of applicability. Almost every concept which can be implemented as a singleton can also be implemented as a monostate.
A monostate is a class which can have any number of instances, but where every instance has exactly the same state as all others. In terms of implementation, it is equivalent to a singleton: a monostate can be represented as a proxy class which automatically references the unique instance of the singleton, and the singleton can be used in place of a monostate simply by using the singleton’s global instance access function wherever the code created a new monostate.
From a design point of view, I tend to consider monostates as a globally weaker alternative to singletons. My reasoning is that a programmer makes the basic assumption that the state of a given instance can only be modified through references to that instance. However, a monostate violates this assumption by allowing the state of an instance to be modified through a reference to another instance. This oddity does not exist for a singleton, where only a single instance exists.
Of course, a monostate does have an advantage whenever the represented concept allows modifications of its state outside of a reference to its instance: this happens, for instance, when representing an entity which evolves outside the program (a filesystem, controlled hardware…) and which explicitly violates the above assumption. If that is the case, then it is interesting to use a FooBarView monostate to represent the concept of FooBar so that the name implies that the object itself is only one of many different views over the same autonomous concept.
Therefore, as a rule of thumb, if a hesitation exists between using the Singleton Design Pattern and the Monostate Design Pattern, then one should use a singleton unless by its very definition the represented unique-and-global-state will change outside the application.
Misconceptions
The Singleton Design Pattern carries several misconceptions, which often lead to its misuse in a situation where it is not an accurate representation of the concepts at hand (and thus a need for refactoring when the mismatch between pattern and concept becomes clear) and to the usage of unrelated arguments in defense of its use.
- “I will use the Singleton Design Pattern because using global variables is not good object-oriented practice.” This is the single most encountered misuse of the pattern. It often finds its roots in the affirmations that “global variables are evil” (and thus should be avoided) and that “design patterns enforce good design” (and thus should be used). Both affirmations are incorrect, or at least partially erroneous.First, global variables are not evil in themselves. What is dangerous is a hard-coded reference to global mutable state : the fact that a piece of code is bound by its very implementation to a bit of mutable state, so that this binding cannot be altered or customized by the user of the code. The hard-coded binding is what makes the code difficult to reuse and thus creates a bad object-oriented practice. However, both global variables and singletons, when accessed directly by the using code, create that same hard-coded binding, and thus share the same issue (which stems, in fact, from the need to have hard-coded access to global mutable state, regardless of how that state is represented).
Then, design patterns are not a silver bullet which automatically enforces good design. Design patterns are bits of high-level vocabulary which allows one to describe a situation or problem using fewer words, which lets the brain focus on the relevant words instead of the details. Using a design pattern to describe something which does not fit that pattern, however, is akin to calling “a tool which is used to drive nails into planks” a “hammer”: you will be in trouble when you notice the “hammer” was in fact a “nailgun”.
In short, using a singleton to replace a variable is a misuse of the design pattern, which violates the third prerequisite (the impossibility to have more than one instance).
- “I will use a singleton to correct a technical issue related to the use of global variables, even though that issue does not prevent the creation of multiple instances.” The technical issues often cited here are the resolution of the initialization order problem (making sure that a global will be initialized before another variable which needs to use it during its initialization) and the possibility of lazy creation (a global variable might exist in memory for a while even if the program never uses).The Singleton Design Pattern can solve these issues. However, the techniques it uses are orthogonal to the techniques used to restrict it to one instance only. Therefore, using a singleton to solve the problem and then removing the one-instance restriction (usually by making the constructor public) will result in a more accurate description, and is thus preferable to both singletons and global variables.
- “I will only ever need one instance of this class, therefore I will use a singleton.” This violates the third prerequisite, and possibly also the fourth. Again, a singleton represents the inability for an additional instance to be created. If your object could be safely instantiated twice, but the application you are writing only uses one instance, then adding code to enforce the uniqueness of the instance is both in contradiction with the nature of the concept you are representing (because it supports multiple instances) and completely useless (because the application never attempts to create two instances anyway).If the third prerequisite is not satisfied, there are plenty of alternative solutions to use to achieve your goal (the most elementary example being the implementation of a singleton minus the one-instance-only restriction).
- “I have made this a singleton, so that I don’t have to pass it to everywhere it is needed.” This is a violation of the first prerequisite. The only reason to turn some functionality into an object is because you wish to group the related state together in a manner which can then be manipulated by functions as a local variable, an argument or a return value.If your representation of the concept at hand does not involve any such manipulation, then a far better representation is to use a good old procedural interface for the concept. If your code could be rewritten with minimal to a procedural solution (by replacing the get-instance-and-call-method statements with call-procedure statements), then your code is implicitly procedural: correct object-oriented code is usually much harder to convert to procedural style. Therefore, since your code is procedural, it is both easier and more transparent to represent it using procedural means than by diverting object-oriented means from their intended purpose.
A correct object-oriented use of the Singleton Design Pattern involves using the singleton class to implement an interface, and then pass the singleton to code which is applied to that interface. And so, not only does a singleton not avoid passing the instance around, but it requires doing so.
Advantages
The main advantage of the singleton is that it is a design pattern: a name which can be instantly associated by any remotely competent software engineer to a the elementary properties of “only one instance” and “globally accessible”. This is an exceedingly important notion: instead of spending precious time writing documentation which painstakingly describes the exact behavior of a given piece of code, being careful not to imply false properties and to be exhaustive in your enumeration of all cases, and also having the user read that entire documentation twice to make sure he understood it correctly, you can simply describe the class’ instantiation policy as “Singleton” and be done with it.
Sometimes, if the intended usage of a public library class is to use a single provided global instance (even if there is no technical reason to limit yourself to a single instance) provided by the library, then I would perhaps go as far as label that class a singleton, in order to forward the point of intended usage despite the violation of prerequisite three.
However, for a class that is to be used internally, and where the users of the code are also its developers, I would not consider mislabeling: conveying a meaning which is incorrect to an user is acceptable, because the user is not expected to know about the implementation (and, for all he knows, perhaps there is a technical limitation on the number of instances), whereas conveying an incorrect meaning to a fellow developer is not.
The special treatment provided to classes in several programming languages make singletons and monostates preferable alternatives to normal procedural modules. For instance, PHP5 provides autoloading support for classes (the file for a class is loaded when that class is used in the source instead of having to be loaded manually beforehand) which makes class-based implementations of modules better. Similarly, since ECMAScript provides no namespace functionality, using a single-instance global-access object as a namespace is a valid and somewhat frequent approach.
Conclusion
A singleton is an excellent tool for describing an unique and globally accessible concept, and there is a simple checklist to determine whether a concept qualifies for representation as a singleton. However, using the singleton design pattern to represent a concept which does not have the two required properties (for instance, by altering the concept by force to make it fit) generally causes more harm than good, by misrepresenting the actual concept being manipulated.
Hi. I'm Victor Nicollet,
The best page on Singletons.