Buy or borrow a copy of GoF
The original GoF book says the following in the Implementation part of Singleton. Note: Instance
is the same as the Java getInstance()
.
- Ensuring a unique instance [...]
- Subclassing the Singleton class. The main issue is not so much defining the subclass but installing its unique instance so that clients will be able to use it. In essence, the variable that refers to the singleton instance must get initialized with an instance of the subclass. The simplest technique is to determine which singleton you want to use in the Singleton's
Instance
operation. An example in the Sample Code shows how to implement this technique with environment variables.
Another way to chose the subclass of Singleton is to take the implementation ofInstance
out of the parent class and put it in the subclass. That lets a C++ programmer decide the class of singleton at link-time (e.g., by linking in an object file containing a different implementation) but keeps it hidden from the clients of the singleton.
The link approach fixes the choice of singleton class at link-time, which makes it hard to choose the singleton class at run-time. Using conditional statements to determine the subclass is more flexible, but it hard-wires the set of possible Singleton classes. Neither approach is flexible enough in all cases.
A more flexible approach uses a registry of singletons. Instead of havingInstance
define the set of possible Singleton classes, the Singleton classes can register their singleton instance by name in a well-known registry.
The registry maps between string names and singletons. WhenInstance
needs a singleton, it consults the registry, asking for the singleton by name.
The GoF book goes on to show how registries work.
Here's the Sample Code using the environment variable:
Now let's consider what happens when there are subclasses... We'll select the [subtype] through an environment variable [...]
MazeFactory* MazeFactory::Instance () {
if (_instance == 0) {
const char* mazeStyle = getenv("MAZESTYLE");
if (strcmp(mazeStyle, "bombed") == 0 {
_instance = new BombedMazeFactory;
} else if (strcmp(mazeStyle, "enchanted") == 0) }
_instance = new EnchantedMazeFactory;
// ... other possible subclasses
} else { // default
_instance = new MazeFactory;
}
}
return _instance;
}