A simple example usage of a Singleton pattern using a global session counter.
Namespace:
CA.Examples.Patterns.GOF.Singleton.ExampleAssembly: CA.Examples (in CA.Examples.dll) Version: 1.0.0.0 (1.0.0.0)
Remarks
This Example Shows:
CopyC#
- 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:
//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); } } }