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