Wednesday, February 14, 2007

Design Patterns in C#. Part 1 Singleton Pattern

Design Patterns are a useful part of software development reuse. Design Patterns introduce a common problem and common solution to said problem. DP's are usually broken into 3 categories:

Creation Patterns:
As the name suggests, deals with the Creation of Objects
Structural Patterns:
Ease design by identifying a simple way to realize relationships between entities
Behavioral Patterns:
Identify common communication patterns between objects

Design Patterns are bigger in the Java world than they are in the .NET world. It's only in the last couple of years that I come across design patterns and their usefulness.

The most common design pattern, and the easiest to understand is the Singleton Pattern.

The definition of the Singleton Pattern is, "Ensure a class has only one instance and provide a global point of access to it."

Which means that the class will only allow one instance of itself to exist. We do this by hiding the constructor of the object and publishing a public method to instantiate the object.

Example:

namespace Singleton
{
  class Program
  {
    static void Main(string[] args)
    {
      ClassicSingleton s1 = ClassicSingleton.CreateInstance();
      ClassicSingleton s2 = ClassicSingleton.CreateInstance();
      //if new classes were being created, values should both be 1
      Console.WriteLine(s1.CountValue());
      //if singleton works then should output 2
      Console.WriteLine(s2.CountValue());

      Console.Read();

    }
  }


  public class ClassicSingleton
  {
    private ClassicSingleton(){}

    private static ClassicSingleton instance;
    public static ClassicSingleton CreateInstance()
    {
      //if instance doesn't exist create new instance
      if (instance == null)
      {
        instance = new ClassicSingleton();
      }
      return instance;
    }

    //small method to prove only one instance gets initiated
    private int counter = 0;

    public string CountValue()
    {
      return (counter += 1).ToString();
    }
  }
}

The above example is using the classic singleton approach. As you can see it is fairly straight forward and easy to understand.

This example is fine in a single threaded case, but in a multi-threaded application it is possible for an instance to exist on separate threads. To eliminate this issue we change the CreateInstance method to include a lock and another check:

public static ClassicSingleton CreateInstance()
{
  //if instance doesn't exist create new instance
  if (instance == null)
  {
    lock (typeof(ClassicSingleton)) ;
    if (instance == null)
    {
      instance = new ClassicSingleton();
    }
  }
  return instance;
}

These two above examples are using fairly standard approaches to creating a Singleton Pattern and is how you would probably expect to see things in the Java world. C# creators (and VB.NET too) new about Design Patterns when they were creating the language, and added a few nice features that makes it easier to do things such as this. The below is a Singleton Pattern creation the .NET way:

sealed class DotNetSingleton
{
  private DotNetSingleton() { }

  public static readonly DotNetSingleton CreateInstance = new DotNetSingleton();

  //small method to prove only one instance gets initiated
  private int counter = 0;

  public string CountValue()
  {
    return (counter += 1).ToString();
  }
}

As you can see from above the .NET version is much simpler. We create a static readonly property of type DotNetSingleton. Because it is marked static readonly it can only ever have one instance of DotNetSingleton. Note the class is now a sealed class, meaning it can't be inherited.

I am hoping to introduce several Design Patterns in the next few posts, but there are also several great resources on the net.

Do Factory is probably a good place to start, but as usual Google is your friend!

Next time, the Factory Pattern.

No comments: