Design Pattern: Singleton

Posted by gabriel, Wed Jul 16 12:31:00 UTC 2008

This is the first post on a series about Design Patterns using C#. I will not publish all the articles in a sequence but you can expect from time to time to have a new post about some pattern.

The first pattern I want to talk about is the Singleton.

Objective

You need a singleton when your application require one and only one instance of a single class and also that this instance can be accessed whenever necessary.

Case Scenario

Imagine that you want a Logger class that will store all messages in a internal list. You need the hold the all the messages in a single place. If you had more than one instance of a Logger class you would have the messages scattered over the various instances. To avoid this will use a singleton.

The Solution

We are going to create a Logger class in our example.

The first issue the singleton should handle is how to prevent users from creating multiple instances of a class. To achieve this you have to block (hide) the constructor. This can be done making it private.


private Logger() { }

Now the that the constructor is private how can you instantiate the class? You are right, you can’t do it from outside the class so we are going to do it from the inside. Since we need to keep the one instance we create we need a variable to hold it. We are going to declare this variable as static so that we don’t need the class to be instantiated in order to keep the value.


//this will hold our unique instance
private static Logger instance = null;

The next step is to come up with a way to create the only instance and at the same time gain Access to that instance. This can be done using a static method that will check the instance variable and if it is null it will create a new instance and return it, if it’s not null it will return the previously create instance.


        public static Logger Instance()
        {
            //if the instance is null you have to instantiate it
            if (instance == null)
            {
                instance = new Logger();
            }
            return instance;
        }

This is all we need for our singleton but we still need to add the functionality for the Logger class. We need a list to store the messages, a method to add new messages and a method to print all the messages already stored. Here is the code for it:


        //holds all the messages
        private List<string> messages = new List<string>();

        //add a new message to the Logger
        public void Log(string message)
        {
            messages.Add(message);
        }

        public void PrintAllMessages()
        {
            foreach (string message in messages)
            {
                Console.WriteLine(message);
            }
        }

Here is the code for the whole class:


    public class Logger
    {
        private static Logger instance = null;

        private Logger() { }

        public static Logger Instance()
        {
            //if the instance is null you have to instantiate it
            if (instance == null)
            {
                instance = new Logger();
            }
            return instance;
        }

        //holds all the messages
        private List<string> messages = new List<string>();

        //add a new message to the Logger
        public void Log(string message)
        {
            messages.Add(message);
        }

        public void PrintAllMessages()
        {
            foreach (string message in messages)
            {
                Console.WriteLine(message);
            }
        }
    }

How to use it

Using the singleton is easy, the only difference from normal class use is that when you need an instance of the object you will not be able to call the constructor (it’s private now) so you need to request an instance through the Instance() method that we created.

In our usage examples I’ll declare two logger variables and pass different messages to each one. Since there’s only one instance both these variables will have references to the same object. This can be verified when you call the PrintAllMessages method of any of the loggers. You’ll notice that they will print all the messages that were passed to any of the variables.

Here is the code so you can test it at home:


    class Program
    {
        static void Main(string[] args)
        {
            Logger logger1 = Logger.Instance();
            Logger logger2 = Logger.Instance();

            logger1.Log("loading one");
            logger2.Log("loading two");

            logger1.Log("Success");
            logger2.Log("Failure");

            logger1.PrintAllMessages();
        }
    }

That’s it for the Singleton, I hope this is useful to someone somewhere :-)

Filed Under: Tips and Tutorials | Tags: C# Design Patterns

Comments

Have your say

A name is required. You may use HTML in your comments.