From 744e5cd406d6e369c69add4933e3a06ac40cc0b5 Mon Sep 17 00:00:00 2001 From: Claudiu Farcas Date: Sat, 17 Apr 2021 17:48:22 +0300 Subject: [PATCH] WIP more creational patterns --- Program.cs | 6 +- creational/prototype/PrototypeSample.cs | 19 +++++ creational/singleton/SingletonSample.cs | 106 ++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 creational/prototype/PrototypeSample.cs create mode 100644 creational/singleton/SingletonSample.cs diff --git a/Program.cs b/Program.cs index 702a022..df6fd59 100644 --- a/Program.cs +++ b/Program.cs @@ -5,6 +5,8 @@ using design_patterns.creational.fluentbuilder; using design_patterns.creational.functionalbuilder; using design_patterns.creational.factory; using design_patterns.creational.facadebuilder; +using design_patterns.creational.singleton; +using design_patterns.creational.prototype; namespace design_patterns { @@ -19,7 +21,9 @@ namespace design_patterns // await AbstractFactorySample.Run(); // await FluentBuilderSample.Run(); // await FunctionalBuilderSample.Run(); - await FacadeBuilderSample.Run(); + // await FacadeBuilderSample.Run(); + // await SingletonSample.Run(); + await PrototypeSample.Run(); } catch (System.Exception ex) { diff --git a/creational/prototype/PrototypeSample.cs b/creational/prototype/PrototypeSample.cs new file mode 100644 index 0000000..014676e --- /dev/null +++ b/creational/prototype/PrototypeSample.cs @@ -0,0 +1,19 @@ +using System; +using System.Threading.Tasks; + +namespace design_patterns.creational.prototype +{ + /// + /// Prototype is a creational design pattern that + /// lets you copy (clone, deep copy) existing objects without making + /// your code dependent on their classes. + /// + public class PrototypeSample + { + public static async Task Run() + { + Console.WriteLine("Creational - Prototype"); + + } + } +} \ No newline at end of file diff --git a/creational/singleton/SingletonSample.cs b/creational/singleton/SingletonSample.cs new file mode 100644 index 0000000..270f5ae --- /dev/null +++ b/creational/singleton/SingletonSample.cs @@ -0,0 +1,106 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace design_patterns.creational.singleton +{ + /// + /// Singleton is a creational design pattern that + /// lets you ensure that a class has only one instance, + /// while providing a global access point to this instance. + /// + /// https://refactoring.guru/design-patterns/singleton + /// + /// + /// The Singleton pattern solves two problems at the same time, + /// violating the Single Responsibility Principle: + /// 1. Ensure that a class has just a single instance. + /// (ex: shared resource, a database or a file) + /// 2. Provide a global access point to that instance. + /// + /// Solution: + /// - Make the default constructor private, to prevent other objects + /// from using the new operator with the Singleton class + /// - Create a static creation method that acts as a constructor. + /// + /// Problem: + /// - Testability + /// - usage of singleton leads to missuse and + /// wrong software design decisions + /// + /// Solution: + /// - AVOID using singleton class, instead use DI containers + /// and configure the container to define lifetime of class as + /// as singleton + /// + public class SingletonSample + { + public static async Task Run() + { + Console.WriteLine("Creational - Singleton"); + + var inst1 = SingletonDatabase.Instance; + var data = inst1.GetData(Guid.NewGuid().ToString()); + Console.WriteLine($"data : {data}"); + + var inst2 = SingletonDatabase.Instance; + Console.WriteLine($"Are inst1 and inst2 the same? {inst1.Equals(inst2)}"); + + var task1 = Task.Factory.StartNew(() => { + var instPerThread1 = PerThreadSingletonDatabase.Instance.GetData("pth"); + Console.WriteLine($"instPerThread1 {instPerThread1}"); + }); + + var task2 = Task.Factory.StartNew(() => { + var instPerThread2 = PerThreadSingletonDatabase.Instance.GetData("pth"); + Console.WriteLine($"instPerThread2 {instPerThread2}"); + }); + Task.WaitAll(task1, task2); + + } + } + + public interface IDatabase { + string GetData(string id); + } + + /// + /// singleton class + /// + public class SingletonDatabase : IDatabase + { + private SingletonDatabase() { + //init resources + Console.WriteLine("singleton resources init"); + } + + // lazy initialization of the class + private static Lazy instance = + new Lazy(() => new SingletonDatabase()); + public static SingletonDatabase Instance { get { return instance.Value; } } + public string GetData(string id) + { + return $"Data {id}"; + } + } + + /// + /// singleton per thread + /// + public class PerThreadSingletonDatabase : IDatabase + { + private PerThreadSingletonDatabase() { + //init resources + Console.WriteLine("per thread singleton resources init"); + } + + // declare and instantiate object into local thread scope + private static ThreadLocal threadInstance = + new ThreadLocal(() => new PerThreadSingletonDatabase()); + public static PerThreadSingletonDatabase Instance { get { return threadInstance.Value; } } + public string GetData(string id) + { + return $"Data {id} from ThreadId: {Thread.CurrentThread.ManagedThreadId}"; + } + } +} \ No newline at end of file