Blog Archives

Singleton Pattern

Highlander

 

I did never really care about programming patterns. I had to come up with ideas when I needed them. And back in the Commodore 64 ages, when I wrote my first “Hello World” program in Basic, there was no book about patterns anyway.

When you only allow one object instance, that is called Singleton.

Have you ever come across Remoting? You send a request to a server. There is a choice between Singleton and SingleCall. It basically means that you:

  • Always use the same object or
  • create a new object for each request.

Let’s say you order 4 pints of beer using your tablet PC rather than calling the sexy, blond, and 18-year-old waitress. You obviously want 4 pints at once. Therefore the correct choice would be SingleCall; 4 distinct objects. The geeky waitress reacts. She responds via her high-tech cash register: “Who are you?”. She could ask that 10 times and unless you get upset, you would always give the same answer. Any good programmer realizes that this would only require one object instance – a Singleton.

There are several ways to do this. The conceptual idea is pretty easy. (Wikipedia has some more details.) In this post I am only giving you my favourite pattern, which should always work. You don’t need more unless you want to show off with some cheap stuff.

 

Example:

Remove the sealed keyword in case you need to make the class inheritable.
Notice the double-check if (_Instance == null) ...

The reason is:

  • The first check avoids entering the lock in 99.9999% of the calls. You save precious processor time.
  • The second check avoids an unlikely multithreading problem. A thread A could enter the lock and not finish before a thread B arrives. B has to wait in front of the lock. A exits the lock, now B enters the lock. Without the second check, B would now create a new instance. And this is, what we are trying to avoid.

 

using System;

namespace Singleton {

  public sealed class JustOne {
    private static readonly object _Lock = new object();
    private static JustOne _Instance = null;
    private JustOne() { }

    public static JustOne Instance {
      get {
        if (_Instance == null) {
          lock (_Lock) {
            if (_Instance == null) _Instance = new JustOne();
          }
        }
        return _Instance;
      }
    } //

    public new string GetHashCode() { return base.GetHashCode().ToString(); }
  } // class

  class Program {

    static void Main(string[] args) {
      JustOne A = JustOne.Instance;
      JustOne B = JustOne.Instance;
      Console.WriteLine("HashCode of object A: " + A.GetHashCode());
      Console.WriteLine("HashCode of object B: " + B.GetHashCode());      

      Console.ReadLine();
    } // main

  } // class
} // namespace