Singleton Pattern   «Prev  Next»
Lesson 11Variations on the Singleton Pattern
ObjectiveWrite a Class that uses an Extension to the Singleton Pattern

Write Class that uses an Extension to the Singleton Pattern

Patterns are not written in stone. You can and should adjust them to meet your needs. Sometimes the techniques in a pattern can be tweaked to create slightly different but related patterns.
For example, suppose you need a class that has exactly two instances instead of exactly one. You can still use the tricks you learned with the Singleton pattern (a non-public constructor[1] and a public static accessor method[2] to do this.
You just need to change it slightly by passing some sort of argument to the accessor method that specifies which instance is required.
One possible use of this might be to implement a queued pool of objects.

For instance, Java threads, though lighter weight than processes, still have nontrivial overhead associated with their creation. If you need to spawn many of them (for instance, imagine a Web server that spawns a thread for each connection), it is often more efficient to reuse threads.
A variant of the Singleton pattern can be developed that stores all created objects in an internal list, and, when a new thread is requested, returns any idle threads in the list. However, if no idle threads are available, a new thread is constructed and returned.
In many ways this pattern does not have the same motivation or purpose as the Singleton. However, it uses the essential ideas of the Singleton.

Enforcing the Singleton's Uniqueness

A few language-related techniques are of help in enforcing the Singleton's uniqueness. We have already used a couple of them: The default constructor and the copy constructor are private. The latter measure disables code such as this:
Singleton shifty(*Singleton::Instance()); // error!
// Cannot make 'shifty' a copy of the (Singleton) object returned by Instance

If you do not define the copy constructor, the compiler does its best to be of help and defines a public one for you. Declaring an explicit copy constructor disables automatic generation, and placing that constructor in the private section yields a compile-time error on shifty's definition.
Another slight improvement is to have Instance return a reference instead of a pointer. The problem with having Instance return a pointer is that callers might be tempted to delete it. To minimize the chances of that happening, it is safer to return a reference:
// inside class Singleton
static Singleton& Instance();

Another member function silently generated by the compiler is the assignment operator. Uniqueness is not directly related to assignment, but one obvious consequence of uniqueness is that you cannot assign one object to another because there aren't two objects to start with. For a Singleton object, any assignment is a self-assignment, which does not make much sense anyway; thus, it is worthwhile to disable the assignment operator (by making it private and never implementing it).
The last coat of the armor is to make the destructor private. This measure prevents clients that hold a pointer to the Singleton object from deleting it accidentally.
After the enumerated measures are added, Singleton's interface looks like the following.
class Singleton {
 Singleton& Instance();
 // ----- operations ...
 Singleton(const Singleton&);
 Singleton& operator=(const Singleton&);

Dual Pattern - Exercise

In this exercise, you will write a class that is a variation of the Singleton.
Dual Pattern - Exercise

[1]constructor: A pseudo-method that creates an object.

[2]accessor method: A method which allows other classes to read (but not change) the values of the attributes. Accessor methods are also known as getter methods. Accessor methods are public methods that merely return the value of the attribute. See also getter method.