Software Design Blog - Singleton Pattern Simple solutions to solve complex problems / http://www.rssboard.org/rss-specification BlogEngine.NET 3.1.1.0 en-US /opml.axd http://www.dotnetblogengine.net/syndication.axd Jay Strydom Software Design Blog 0.000000 0.000000 Evolution of the Singleton Design Pattern in C# <p>This post is focused on the evolutionary process of implementing the <a href="https://en.wikipedia.org/wiki/Singleton_pattern" target="_new">singleton design pattern</a> that restricts the instantiation to one object.</p> <p>We will start with a simple implementation and move onto a thread safe example using locking. A comparison is made using Lazy Initialization and we will complete the post with a loosely coupled singleton solution using Dependency Injection.</p> <a href="/Downloads/SingletonExample.zip" role="button" class="btn btn-primary btn-sm">Download Source Code</a> <h3>Singleton Components</h3> <p>We will use logging as our singleton use-case. The logging interface and implementation shown below will write to the console when the ConsoleLogger is instantiated.</p> <pre class="brush: c-sharp;"> public interface ILogger { void Log(string message); } public class ConsoleLogger : ILogger { public ConsoleLogger() { Console.WriteLine("{0} constructed", GetType().Name); } public void Log(string message) { Console.WriteLine(message); } } </pre> <h3>Single Thread Singleton</h3> <p>Below is a simple implementation of a singleton.</p> <pre class="brush: c-sharp;"> public class SingleThreadLogger { private static ILogger _instance; public static ILogger Instance { get { if (_instance == null) { _instance = new ConsoleLogger(); } return _instance; } } } </pre> Calling the singleton in a single thread from the console: <pre class="brush: c-sharp;"> static void Main(string[] args) { SingleThreadLogger.Instance.Log("Hello World"); SingleThreadLogger.Instance.Log("Hello World"); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World Hello World </pre> Calling the singleton using multiple threads from the console: <pre class="brush: c-sharp;"> static void Main(string[] args) { Parallel.Invoke(() =&gt; SingleThreadLogger.Instance.Log("Hello World"), () =&gt; SingleThreadLogger.Instance.Log("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World ConsoleLogger constructed Hello World </pre> <div class="alert alert-danger" role="alert"> <b>Oops!</b> Two instances of the logger was instantiated. </div> <h3>Thread Safe Singleton</h3> Below is an example of a poorly implemented locking approach around the constructor of the ConsoleLogger: <pre class="brush: c-sharp;"> public class ThreadLockConstructorLogger { private static ILogger _instance; private static readonly Object _lock = new object(); public static ILogger Instance { get { if (_instance == null) { lock (_lock) { // WARNING: Multiple instantiation _instance = new ConsoleLogger(); } } return _instance; } } } </pre> Calling the singleton using multiple threads from the console: <pre class="brush: c-sharp;"> static void Main(string[] args) { Parallel.Invoke(() =&gt; ThreadLockConstructorLogger.Instance.Log("Hello World"), () =&gt; ThreadLockConstructorLogger.Instance.Log("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World ConsoleLogger constructed Hello World </pre> <div class="alert alert-danger" role="alert"> <b>Oops!</b> Two instances of the logger was instantiated. </div> <p>The ThreadLockConstructorLogger class has the classic <a href="https://en.wikipedia.org/wiki/Double-checked_locking" target="_blank">double-checked locking</a> bug. The first thread acquired the lock and is busy on line 15 while the second thread is waiting for the lock to be released on line 13. Once the second thread acquires the lock, another instance will be created on line 15.</p> <p>We can solve the problem by implementing the double locking solution as shown below, where we perform another check to verify that the class has not been instantiated once the lock has been acquired.</p> <pre class="brush: c-sharp;"> public class ThreadLockWriteLogger { private static ILogger _instance; private static readonly Object _lock = new object(); public static ILogger Instance { get { if (_instance == null) { lock (_lock) { if (_instance == null) { _instance = new ConsoleLogger(); } } } return _instance; } } } </pre> Calling the singleton using multiple threads from the console: <pre class="brush: c-sharp;"> static void Main(string[] args) { Parallel.Invoke(() =&gt; ThreadLockWriteLogger.Instance.Log("Hello World"), () =&gt; ThreadLockWriteLogger.Instance.Log("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World Hello World </pre> <div class="alert alert-success" role="alert"> <b>Success!</b> Only one instance of the logger was created. </div> <h3>Lazy Instantiated Singleton</h3> <p>A simplified approach is to use <a href="https://msdn.microsoft.com/en-us/library/dd997286(v=vs.110).aspx" target="_blank">lazy instantiation</a> because by default, Lazy<t> objects are thread-safe as shown below.</t></p> <pre class="brush: c-sharp;"> public class LazyLogger { private static readonly Lazy&lt;ILogger&gt; _instance = new Lazy&lt;ILogger&gt;(() =&gt; new ConsoleLogger()); public static ILogger Instance { get { return _instance.Value; } } } </pre> Calling the lazy singleton using multiple threads from the console: <pre class="brush: c-sharp;"> static void Main(string[] args) { Parallel.Invoke(() =&gt; LazyLogger.Instance.Log("Hello World"), () =&gt; LazyLogger.Instance.Log("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World Hello World </pre> <div class="alert alert-success" role="alert"> <b>Success!</b> Only one instance of the logger was created. </div> <h3>Dependency Injection Singleton</h3> <p>A singleton is considered an anti-pattern due to the following reasons:</p><p> </p><ul> <li><b>Hidden dependencies</b> makes it is hard to tell what a class is dependent on when the dependencies are not explicitly defined (ie: the constructor).</li> <li><b>Tight coupling</b> occurs when singletons are hardcoded into an application as a static method and unnecessary complicates mocking dependencies in automated tests.</li> <li><b>Single Responsibility Principle</b> is violated since the creation of an object is mixed with the lifecycle management of the application.</li> </ul> <p>Dependency Injection (DI) can remedy the problems above. Let's have a look at the example below that consists of a WriteMessageAction class with a dependency on the ILogger interface.</p> <pre class="brush: c-sharp;"> public interface IAction&lt;in T&gt; { void Do(T message); } public class WriteMessageAction : IAction&lt;string&gt; { private readonly ILogger _logger; public WriteMessageAction(ILogger logger) { if (logger == null) throw new ArgumentNullException("logger"); _logger = logger; } public void Do(string message) { _logger.Log(message); } } </pre> We can use Unity to manage the lifecycle of the ILogger instance as shown below. <pre class="brush: c-sharp;"> static void Main(string[] args) { var container = new UnityContainer(); container.RegisterType&lt;ILogger, ConsoleLogger&gt;( new ContainerControlledLifetimeManager()); container.RegisterType&lt;IAction&lt;string&gt;, WriteMessageAction&gt;("One"); container.RegisterType&lt;IAction&lt;string&gt;, WriteMessageAction&gt;("Two"); var actions = container.ResolveAll&lt;IAction&lt;string&gt;&gt;(); actions.ForEach(action =&gt; action.Do("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed Hello World Hello World </pre> <div class="alert alert-success" role="alert"> <b>Success!</b> Only one instance of the logger was created. </div> The key is on line 4 to 5, since we pass in "new ContainerControlledLifetimeManager()" to register the object as a singleton. By default, unity will create a new instance of an object when we omit the ContainerControlledLifetimeManager constructor parameter as shown below: <pre class="brush: c-sharp;"> { var container = new UnityContainer(); container.RegisterType&lt;ILogger, ConsoleLogger&gt;(); container.RegisterType&lt;IAction&lt;string&gt;, WriteMessageAction&gt;("One"); container.RegisterType&lt;IAction&lt;string&gt;, WriteMessageAction&gt;("Two"); var actions = container.ResolveAll&lt;IAction&lt;string&gt;&gt;(); actions.ForEach(action =&gt; action.Do("Hello World")); Console.ReadLine(); } </pre> <pre> ConsoleLogger constructed ConsoleLogger constructed Hello World Hello World </pre> <div class="alert alert-warning" role="alert"> <b>Note:</b> A new logger instance was created as defined in our unity registration. </div> /post/evolution-of-the-singleton-design-pattern jay@webdevelopment.co.nz /post/evolution-of-the-singleton-design-pattern#comment /post.aspx?id=7f16077c-0a52-43b2-a8aa-9ed73f9e45b0 Wed, 02 Dec 2015 08:58:00 +1300 Design Patterns Singleton Pattern Software Design C# Singleton Dependency Injection Design Patterns .NET Jay Strydom /pingback.axd /post.aspx?id=7f16077c-0a52-43b2-a8aa-9ed73f9e45b0 0 /trackback.axd?id=7f16077c-0a52-43b2-a8aa-9ed73f9e45b0 /post/evolution-of-the-singleton-design-pattern#comment /syndication.axd?post=7f16077c-0a52-43b2-a8aa-9ed73f9e45b0