From 7973a53cc47b324464167a21568a8ee6fc0136c8 Mon Sep 17 00:00:00 2001 From: eminencegrs Date: Thu, 8 Feb 2024 18:29:21 +0100 Subject: [PATCH] Add Singleton. --- .../DesignPatterns.Visitor.UnitTests.csproj | 2 +- .../DesignPatterns.Visitor.csproj | 3 +- ...nPatterns.AbstractFactory.UnitTests.csproj | 3 +- .../DesignPatterns.AbstractFactory.csproj | 3 +- .../DesignPatterns.Singleton.UnitTests.csproj | 40 +++++++++++++++++++ .../SingletonWithLazyTests.cs | 16 ++++++++ .../SingletonWithLockTests.cs | 16 ++++++++ .../DesignPatterns.Singleton.csproj | 14 +++++++ .../DesignPatterns.Singleton/Program.cs | 9 +++++ .../SingletonWithLazy.cs | 16 ++++++++ .../SingletonWithLock.cs | 28 +++++++++++++ DesignPatterns.sln | 14 +++++++ 12 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 Creational/DesignPatterns.Singleton.UnitTests/DesignPatterns.Singleton.UnitTests.csproj create mode 100644 Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLazyTests.cs create mode 100644 Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLockTests.cs create mode 100644 Creational/DesignPatterns.Singleton/DesignPatterns.Singleton.csproj create mode 100644 Creational/DesignPatterns.Singleton/Program.cs create mode 100644 Creational/DesignPatterns.Singleton/SingletonWithLazy.cs create mode 100644 Creational/DesignPatterns.Singleton/SingletonWithLock.cs diff --git a/Behavioral/DesignPatterns.Visitor.UnitTests/DesignPatterns.Visitor.UnitTests.csproj b/Behavioral/DesignPatterns.Visitor.UnitTests/DesignPatterns.Visitor.UnitTests.csproj index ffe9889..c9e5c6a 100644 --- a/Behavioral/DesignPatterns.Visitor.UnitTests/DesignPatterns.Visitor.UnitTests.csproj +++ b/Behavioral/DesignPatterns.Visitor.UnitTests/DesignPatterns.Visitor.UnitTests.csproj @@ -34,4 +34,4 @@ - \ No newline at end of file + diff --git a/Behavioral/DesignPatterns.Visitor/DesignPatterns.Visitor.csproj b/Behavioral/DesignPatterns.Visitor/DesignPatterns.Visitor.csproj index d272bea..c5059fd 100644 --- a/Behavioral/DesignPatterns.Visitor/DesignPatterns.Visitor.csproj +++ b/Behavioral/DesignPatterns.Visitor/DesignPatterns.Visitor.csproj @@ -5,11 +5,10 @@ net8.0 enable enable - DesignPatterns.Visitor - \ No newline at end of file + diff --git a/Creational/DesignPatterns.AbstractFactory.UnitTests/DesignPatterns.AbstractFactory.UnitTests.csproj b/Creational/DesignPatterns.AbstractFactory.UnitTests/DesignPatterns.AbstractFactory.UnitTests.csproj index 031f9ab..b32966c 100644 --- a/Creational/DesignPatterns.AbstractFactory.UnitTests/DesignPatterns.AbstractFactory.UnitTests.csproj +++ b/Creational/DesignPatterns.AbstractFactory.UnitTests/DesignPatterns.AbstractFactory.UnitTests.csproj @@ -4,7 +4,6 @@ net8.0 enable enable - DesignPatterns.AbstractFactory.UnitTests false true @@ -34,4 +33,4 @@ - \ No newline at end of file + diff --git a/Creational/DesignPatterns.AbstractFactory/DesignPatterns.AbstractFactory.csproj b/Creational/DesignPatterns.AbstractFactory/DesignPatterns.AbstractFactory.csproj index 16f68a7..2ff6788 100644 --- a/Creational/DesignPatterns.AbstractFactory/DesignPatterns.AbstractFactory.csproj +++ b/Creational/DesignPatterns.AbstractFactory/DesignPatterns.AbstractFactory.csproj @@ -5,7 +5,6 @@ net8.0 enable enable - DesignPatterns.AbstractFactory @@ -19,4 +18,4 @@ - \ No newline at end of file + diff --git a/Creational/DesignPatterns.Singleton.UnitTests/DesignPatterns.Singleton.UnitTests.csproj b/Creational/DesignPatterns.Singleton.UnitTests/DesignPatterns.Singleton.UnitTests.csproj new file mode 100644 index 0000000..8ed623b --- /dev/null +++ b/Creational/DesignPatterns.Singleton.UnitTests/DesignPatterns.Singleton.UnitTests.csproj @@ -0,0 +1,40 @@ + + + + net8.0 + enable + enable + false + true + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + diff --git a/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLazyTests.cs b/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLazyTests.cs new file mode 100644 index 0000000..cc45884 --- /dev/null +++ b/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLazyTests.cs @@ -0,0 +1,16 @@ +using Shouldly; +using Xunit; + +namespace DesignPatterns.Singleton.UnitTests; + +public class SingletonWithLazyTests +{ + [Fact] + public void Given_WhenCreateSingletonWithLazy_ThenSameInstancesReturned() + { + var firstInstance = SingletonWithLazy.Instance; + var secondInstance = SingletonWithLazy.Instance; + + firstInstance.ShouldBe(secondInstance); + } +} diff --git a/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLockTests.cs b/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLockTests.cs new file mode 100644 index 0000000..904917d --- /dev/null +++ b/Creational/DesignPatterns.Singleton.UnitTests/SingletonWithLockTests.cs @@ -0,0 +1,16 @@ +using Shouldly; +using Xunit; + +namespace DesignPatterns.Singleton.UnitTests; + +public class SingletonWithLockTests +{ + [Fact] + public void Given_WhenCreateSingletonWithLock_ThenSameInstancesReturned() + { + var firstInstance = SingletonWithLock.Instance; + var secondInstance = SingletonWithLock.Instance; + + firstInstance.ShouldBe(secondInstance); + } +} diff --git a/Creational/DesignPatterns.Singleton/DesignPatterns.Singleton.csproj b/Creational/DesignPatterns.Singleton/DesignPatterns.Singleton.csproj new file mode 100644 index 0000000..9079cb5 --- /dev/null +++ b/Creational/DesignPatterns.Singleton/DesignPatterns.Singleton.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/Creational/DesignPatterns.Singleton/Program.cs b/Creational/DesignPatterns.Singleton/Program.cs new file mode 100644 index 0000000..7193e17 --- /dev/null +++ b/Creational/DesignPatterns.Singleton/Program.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +var host = Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration(ctx => ctx.AddJsonFile("appsettings.json")) + .ConfigureServices(services => { }) + .Build(); + +Console.WriteLine(); \ No newline at end of file diff --git a/Creational/DesignPatterns.Singleton/SingletonWithLazy.cs b/Creational/DesignPatterns.Singleton/SingletonWithLazy.cs new file mode 100644 index 0000000..4484082 --- /dev/null +++ b/Creational/DesignPatterns.Singleton/SingletonWithLazy.cs @@ -0,0 +1,16 @@ +namespace DesignPatterns.Singleton; + +public class SingletonWithLazy +{ + private static readonly Lazy instance = new(() => new SingletonWithLazy()); + + /// + /// The private constructor is declared to prevent instantiation directly, via calling a default constructor. + /// + private SingletonWithLazy() + { + Console.WriteLine($"An instance of {nameof(SingletonWithLazy)} has been created."); + } + + public static SingletonWithLazy Instance => instance.Value; +} diff --git a/Creational/DesignPatterns.Singleton/SingletonWithLock.cs b/Creational/DesignPatterns.Singleton/SingletonWithLock.cs new file mode 100644 index 0000000..d12c870 --- /dev/null +++ b/Creational/DesignPatterns.Singleton/SingletonWithLock.cs @@ -0,0 +1,28 @@ +namespace DesignPatterns.Singleton; + +public class SingletonWithLock +{ + private static SingletonWithLock? instance = null; + private static readonly object lockObj = new(); + + /// + /// The private constructor is declared to prevent instantiation directly, via calling a default constructor. + /// + private SingletonWithLock() + { + Console.WriteLine($"An instance of {nameof(SingletonWithLock)} has been created."); + } + + public static SingletonWithLock Instance + { + get + { + // The cost of executing the lock operation is significantly higher + // in comparison to the straightforward pointer check `instance != null`. + lock (lockObj) + { + return instance ??= new SingletonWithLock(); + } + } + } +} diff --git a/DesignPatterns.sln b/DesignPatterns.sln index ad127ee..1312456 100644 --- a/DesignPatterns.sln +++ b/DesignPatterns.sln @@ -16,6 +16,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Structural", "Structural", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesignPatterns.Decorator", "Structural\DesignPatterns.Decorator\DesignPatterns.Decorator.csproj", "{FA3C4F09-104E-4F7D-9ADB-E7F22917ADF7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesignPatterns.Singleton", "Creational\DesignPatterns.Singleton\DesignPatterns.Singleton.csproj", "{658DB1C6-AC85-4E03-99C4-C79116E558F5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesignPatterns.Singleton.UnitTests", "Creational\DesignPatterns.Singleton.UnitTests\DesignPatterns.Singleton.UnitTests.csproj", "{FFB0861F-5182-40CA-BD19-33BCB0FBA4F6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -42,6 +46,14 @@ Global {FA3C4F09-104E-4F7D-9ADB-E7F22917ADF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {FA3C4F09-104E-4F7D-9ADB-E7F22917ADF7}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA3C4F09-104E-4F7D-9ADB-E7F22917ADF7}.Release|Any CPU.Build.0 = Release|Any CPU + {658DB1C6-AC85-4E03-99C4-C79116E558F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {658DB1C6-AC85-4E03-99C4-C79116E558F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {658DB1C6-AC85-4E03-99C4-C79116E558F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {658DB1C6-AC85-4E03-99C4-C79116E558F5}.Release|Any CPU.Build.0 = Release|Any CPU + {FFB0861F-5182-40CA-BD19-33BCB0FBA4F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FFB0861F-5182-40CA-BD19-33BCB0FBA4F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FFB0861F-5182-40CA-BD19-33BCB0FBA4F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FFB0861F-5182-40CA-BD19-33BCB0FBA4F6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {DCE06EB6-BAB5-4573-AF67-128DBCCDB90C} = {7FF0E83F-EBEB-4103-BCD1-2F100E82FCD1} @@ -49,5 +61,7 @@ Global {0C5CFC73-F6E4-4796-A11C-9CA378B80517} = {AE005ED4-5F0B-4AF9-81AE-AAE3AD6F8901} {1E56CC89-45C1-45F7-9EC8-88D648572816} = {AE005ED4-5F0B-4AF9-81AE-AAE3AD6F8901} {FA3C4F09-104E-4F7D-9ADB-E7F22917ADF7} = {5961ADCC-5FA6-4076-A9F4-C1D3207ABE1A} + {658DB1C6-AC85-4E03-99C4-C79116E558F5} = {AE005ED4-5F0B-4AF9-81AE-AAE3AD6F8901} + {FFB0861F-5182-40CA-BD19-33BCB0FBA4F6} = {AE005ED4-5F0B-4AF9-81AE-AAE3AD6F8901} EndGlobalSection EndGlobal