A simple example usage of a Singleton pattern using a global session counter.

Namespace:  CA.Examples.Patterns.GOF.Singleton.Example
Assembly:  CA.Examples (in CA.Examples.dll) Version: 1.0.0.0 (1.0.0.0)

Remarks

This Example Shows:
  • The use of a a private constructor to prevent this class from been created.
  • A static Instance method as a global entry point
  • the use of a _locker synchronizing object to prevent mutiple threads incrementing or decrementing at the same time

source code:

CopyC#
//Source code from the Code Associate C# code library, Full documentation and latest updates can be found
//@ http://www.codeassociate.com/caapi/
using NUnit.Framework;

namespace CA.Examples.Patterns.GOF.Singleton.Example
{
    public sealed class SessionCounter
    {
        // use a private constructor to prevent this class from been created. 
        private SessionCounter() { }

        // using a lazily initialized static varaible thread safety is guaranteed by the compiler.
        private static readonly SessionCounter _instance = new SessionCounter();

        private object _locker = new object(); //synchronizing object to prevent mutiple threads incrementing or decrementing at the same time.    
        private int _counter = 0; //Instance variables for the Singleton have to be thread safe making coding a little more difficult. In this case a synchronizing object is used.

        public static SessionCounter Instance
        {
            get
            {
                return _instance;
            }
        }


        private void IncrementCounter(bool val)
        {
            // Only one thread can lock the synchronizing object (in this case locker) at a time, and any contending threads are blocked until the lock is released.
            // If more than one thread contends the lock, they are queued – on a "ready queue" and granted the lock on a first-come, 
            // first-served basis as it becomes available, this ensures only one thread can update the counter at a given point in time. 
            lock (_locker)
            {
                if (val)
                    _counter++;
                else
                    _counter--;
            }
        }

        public void Increment()
        {
            IncrementCounter(true);
        }

        public void Decrement()
        {
            IncrementCounter(false);
        }

        public int Value
        {
            get { return _counter; }
        }
    }


    [TestFixture]
    public class SessionCounterUnitTest
    {
        [Test]
        public void TestSessionCounter()
        {
            // Assert SessionCounter.Instance always gets the same instance of the object
            SessionCounter a = SessionCounter.Instance;
            SessionCounter b = SessionCounter.Instance;
            Assert.IsTrue(a == b);

            // Assert Counting is working as expected;
            Assert.AreEqual(0, SessionCounter.Instance.Value);
            SessionCounter.Instance.Increment();
            Assert.AreEqual(1, SessionCounter.Instance.Value);
            SessionCounter.Instance.Decrement();
            Assert.AreEqual(0, SessionCounter.Instance.Value);
        }








    }
}

Inheritance Hierarchy

System..::.Object
  CA.Examples.Patterns.GOF.Singleton.Example..::.SessionCounter

See Also