Singleton pattern

From GPWiki
Jump to: navigation, search

The singleton pattern is implemented by creating a class with a method that creates a new instance of the object if one does not exist. If one does exist it returns a reference to the object that already exists. To make sure that the object cannot be instantiated any other way the constructor is made either private or protected.

Definition

Problem

[1]"Ensure a class only has one instance, and provide a global point of access to it."


Context

  1. All objects need access to a single instance of a class
  2. It is required that no additional instances of the class are created

Solution

  1. Define a class with a private constructor
  2. The class constructs a single instance of itself
  3. Supply a static method that returns a reference to the single instance

UML Diagram

UML Diagram of the Singleton Pattern

A Singleton Class Template in C++

template<class T>
class Singleton
{
  public:
    static T *Instance();           // Create an instance of the object
    static T &ref_getSingleton();   // Get a reference to the object
    static T *ptr_getSingleton();   // Get a pointer to the object
 
  protected:
    Singleton();   // notice that the constructor is NOT public
 
  private:
    static T *m_instance;    // The actual object
};

This is the singleton factory, and it's not so big but can be a bit confusing. The implementation of the getSingleton functions returns the instance of the object.

Creating a Singleton Object

To create an instance of an object as singleton just use the static properties of this class:

  Singleton<Application>::Instance();

Comment surely the above violates the pattern, due to being able to create a separate none singleton Application instance?

To use a singleton version of a class it will have to have one instance, so it would be wise to do a check to see if the instance is created before returning it, and create it if it does not exist.

This means that we will never need an actual member in any class to hold the instance, it's done by the singleton template, I use it for my mouse and keyboard listeners, because there are not often you have the opportunity to have multiples of those.

To access an instance of the class you just use one of the getSingleton functions.

  Singleton<Application>::ptr_getSingleton();

If there is an instance of this it is returned otherwise an instance should be created.

Example of how to use an instanced singleton

(Edit note: I did write this in a confusing way, and did not really understand what I was trying to explain so here are hopefully a better way to explain how to use it)

To give an easy example of how to work with the design pattern I will use this easy keyboard listener:

class Keyboard_Listener
{
  public:
    void keyPressed(const int key) {m_keys[key] = true;} // sets a key status to pressed
    bool isKeyPressed(const int key) {return m_keys[key];} // checks a given keys status
 
  private:
    bool m_keys[256]; // not sure how many there are, just a guess
};

Assume that there are some function handling user interaction (i.e. the Win32 uses the window procedure).

If a user press the 'k' key and the keyboard listener should get a notice about it, I use the singleton as a tool to inform the one instance of Keyboard_Listener. In pseudo-code it would be something like:

  if(key_pressed = 'k')
    Singleton<Keyboard_Listener>::ptrGetSingleton()->keyPressed('k');

To check this in the application I use the singleton to ask if the key is pressed, in pseudo code:

  if(Singleton<Keyboard_Listener>::ptrGetSingleton()->isKeyPressed('k'))
    do some stuff;

Putting it Together

This is a small program that makes use of the previous mentioned classes:

int main(void)
{
  int input;
  Singleton<Keyboard_Listener>::Instance();
 
  while(true)
  {
    cin >> input;
    Singleton<Keyboard_Listener>::ptrGetSingleton()->keyPressed(input);
 
    if(Singleton<Keyboard_Listener>::ptrGetSingleton()->isKeyPressed('q'))
    {
      cout << "you pressed q on your keyboard, exiting..." << endl;
      break;
    }
  }
  return 0;
}

That last example just shows some way of using the singleton, when I know that heavy use will be conducted I create a pointer to hold the instance, consider:

  Singleton<Keyboard_Listener>::ptrGetSingleton()->keyPressed(input);

In opposition to:

  Keyboard_Listener *k;
  k = Singleton<Keyboard_Listener>::ptrGetSingleton();
  k->keyPressed;

I believe the latter is a bit easier to work with and the code will be more readable.

You can also use a typedef-statement to make a shorthand notation of the singleton class. That way, you can use a placeholder name of your own choice to point to singleton class.

 typedef Singleton<Keyboard_Listener>::Instance() SingletonKeyboardListener;
 #define KeyboardListener SingletonKeyboardListener::ptrGetSingleton()

Calling the keyPressed() function will then look like this

 KeyboardListener->keyPressed(input);

The compiled code will actually look like the following

 SingletonKeyboardListener::ptrGetSingleton()->keyPressed(input);

With KeyboardListener being replaced by SingletonKeyboardListener::ptrGetSingleton(). You only see the placeholder name, however, so the readability will be improved.

Be aware that if you're using Microsoft Visual Studio, the IntelliSense function might not be able to parse this setup.

External Links

[1]Erich Gamma et al, "Design Patterns: elements of reusable object-oriented software", Addison Wesley (1995)