Software Development Tricky

Wednesday, 6 September 2017

Singleton Pattern

  • Singleton is a creational design pattern that let you ensure that a class has only one instance and provide global access point to this instance.
  • You need to manage single instance with help of static initialization.   

Examples:
  1. Consider Company, there is only one CEO. If you want to create or access CEO object. You should return same CEO object every time. It is applicable for Database, Logging, Prime Minister and Government object etc……
  2.  Imagine one web service that received orders, translate them to other programs and submitted order to the other programs.

    If we created a new object for each submission to next program, we might have 1000 objects trying to simultaneously submit requests to those program. That could cause a problem, if the other programs were not capable of handling as many connection as we had orders.

    So in this situation, we used a singleton, with a queue, to submit orders to the next programs. Our singleton object would accept all orders, hold them in a queue and submit one at a time ((i.e.) synchronously) to the next programs. This allowed other program to handle more submissions
Drawbacks:

  • Singleton doesn’t support inheritance of the class
  • Unit testing is more difficult (because it introduces a global state into an application)
  • The pattern reduces the potential for parallelism within a program, because to access the singleton in a multi-threaded system, an object must be serialized (by locking)
Sample Demo Diagram:

รจ It shown singleton logger instance access from different class.

Sample Demo Program:

(1)    Singleton – No Thread Safe
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace SingletonDesignPattern
{
    public class Logger
    {
        public static Logger _Logger = null;

        public Logger()
        {
            //TODO
        }

        public static Logger GetLogger()
        {
            if (_Logger == null)
            {
                _Logger = new Logger();
            }
            return _Logger;
        }

        public void WriteText(string Text)
        {
            //TODO
        }
    }
}


      In the above the code, when two threads are executed, it always finds an instance which is null and both two thread try to create a new logger object.

In small project, that isn’t a real problem, but if your program expects a single instance of the logger object, this could lead to problems – ones that probably won’t be detected until the program is run in the real world.

(2)    Singleton – Thread Safety Single Check
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
namespace SingletonDesignPattern
{
    public class Logger
    {
        private static Logger _Logger = null;
        private static readonly object _synlock = new object();

        public Logger()
        {
            //TODO
        }

        public static Logger GetLogger()
        {
            lock (_synlock)
            {
                if (_Logger == null)
                {
                    _Logger = new Logger();
                }
                return _Logger;
            }
        }

        public void WriteText(string Text)
        {
            //TODO
        }
    }
}

In the above the code, the thread is locked on a shared object and checks whether an instance has been created or not. This will ensure that only one thread creates an instance. The bigger problem with this is performance. Performance suffers since a lock is required every time an instance is requested.

(3)    Singleton – Thread Safety Double Check
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
namespace SingletonDesignPattern
{
    public class Logger
    {
        private static Logger _Logger = null;
        private static readonly object _synlock = new object();

        public Logger()
        {
            //TODO
        }

        public static Logger GetLogger()
        {
            if (_Logger == null)
            {
                lock (_synlock)
                {
                    if (_Logger == null)
                    {
                        _Logger = new Logger();
                    }
                }
            }
            return _Logger;
        }

        public void WriteText(string Text)
        {
            //TODO
        }
    }
}
In the above the code, the thread is locked on shared object and checks whether an instance has been created or not with double checking

(4)    Singleton – Simple way to implement in .Net (Lazy Instantiation)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
namespace SingletonDesignPattern
{
    public class Logger
    {
        private static readonly Logger _Logger = new Logger();

        public Logger()
        {
            //TODO
        }

        public static Logger GetLogger()
        {
            return _Logger;
        }

        public void WriteText(string Text)
        {
            //TODO
        }
    }
}
In this technique, you just initialize the private static read-only _logger variable with an instance of the logger object, in the same line where you declare it. Then, the GetLogger method returns that value.

If you like this post. Kindly share your valuable comments

1 comment:

Followers