From 043cbf6f27802ff3544d2b151b8c7bc315804cfc Mon Sep 17 00:00:00 2001 From: Omar Bitar Date: Mon, 9 Dec 2024 11:45:29 +0300 Subject: [PATCH] Refactored Singleton Pattern examples for compatibility and thread safety Improved thread safety by adding locking mechanisms in singleton implementations. Refactored to ensure compatibility with C# 4.0 by replacing interpolated strings and expression-bodied members with alternatives. Simplified and standardized singleton instance access. Ensured better encapsulation with private constructors and sealed classes where applicable. Improved readability and consistency across all Singleton Pattern example scripts. --- .../Example1/SingletonPatternExample1.cs | 60 +++++-------------- .../Example2/SingletonPatternExample2.cs | 26 +++----- .../Example3/SingletonPatternExample3.cs | 42 ++++--------- .../Structure/SingletonStructure.cs | 31 ++++------ Unity-Design-Pattern.sln | 17 +++--- 5 files changed, 58 insertions(+), 118 deletions(-) diff --git a/Assets/Creational Patterns/Singleton Pattern/Example1/SingletonPatternExample1.cs b/Assets/Creational Patterns/Singleton Pattern/Example1/SingletonPatternExample1.cs index a0639a8..d1dbcbd 100644 --- a/Assets/Creational Patterns/Singleton Pattern/Example1/SingletonPatternExample1.cs +++ b/Assets/Creational Patterns/Singleton Pattern/Example1/SingletonPatternExample1.cs @@ -16,19 +16,8 @@ public class SingletonPatternExample1 : MonoBehaviour { void Start() { - LoadBalancer b1 = LoadBalancer.GetLoadBalancer(); - LoadBalancer b2 = LoadBalancer.GetLoadBalancer(); - LoadBalancer b3 = LoadBalancer.GetLoadBalancer(); - LoadBalancer b4 = LoadBalancer.GetLoadBalancer(); + var balancer = LoadBalancer.Instance; - // Same instance? - if (b1 == b2 && b2 == b3 && b3 == b4) - { - Debug.Log("Same instance\n"); - } - - // Load balance 15 server requests - LoadBalancer balancer = LoadBalancer.GetLoadBalancer(); for (int i = 0; i < 15; i++) { string server = balancer.Server; @@ -37,56 +26,39 @@ void Start() } } - /// - /// The 'Singleton' class - /// - class LoadBalancer + public sealed class LoadBalancer { + private static readonly object _syncLock = new object(); private static LoadBalancer _instance; - private List _servers = new List(); - private System.Random _random = new System.Random(); - - // Lock synchronization object - private static object syncLock = new object(); + private readonly List _servers = new List { "ServerI", "ServerII", "ServerIII", "ServerIV", "ServerV" }; + private readonly System.Random _random = new System.Random(); - // Constructor (protected) - protected LoadBalancer() - { - // List of available servers - _servers.Add("ServerI"); - _servers.Add("ServerII"); - _servers.Add("ServerIII"); - _servers.Add("ServerIV"); - _servers.Add("ServerV"); - } + private LoadBalancer() { } - public static LoadBalancer GetLoadBalancer() + public static LoadBalancer Instance { - // Support multithreaded applications through - // 'Double checked locking' pattern which (once - // the instance exists) avoids locking each - // time the method is invoked - if (_instance == null) + get { - lock (syncLock) + if (_instance == null) { - if (_instance == null) + lock (_syncLock) { - _instance = new LoadBalancer(); + if (_instance == null) + { + _instance = new LoadBalancer(); + } } } + return _instance; } - - return _instance; } - // Simple, but effective random load balancer public string Server { get { int r = _random.Next(_servers.Count); - return _servers[r].ToString(); + return _servers[r]; } } } diff --git a/Assets/Creational Patterns/Singleton Pattern/Example2/SingletonPatternExample2.cs b/Assets/Creational Patterns/Singleton Pattern/Example2/SingletonPatternExample2.cs index 7c3204f..e147bf9 100644 --- a/Assets/Creational Patterns/Singleton Pattern/Example2/SingletonPatternExample2.cs +++ b/Assets/Creational Patterns/Singleton Pattern/Example2/SingletonPatternExample2.cs @@ -23,35 +23,27 @@ void Update() } } - - /// - /// 某单例manager - /// - public class RenderManager + public sealed class RenderManager { - private static RenderManager instance; + private static RenderManager _instance; + + private RenderManager() { } + public static RenderManager Instance { get { - if (instance == null) + if (_instance == null) { - instance = new RenderManager(); + _instance = new RenderManager(); } - return instance; + return _instance; } } - /// - /// 随便某方法 - /// public void Show() { - Debug.Log("RenderManager is a Singleton !"); + Debug.Log("RenderManager is a Singleton!"); } } - - - - } \ No newline at end of file diff --git a/Assets/Creational Patterns/Singleton Pattern/Example3/SingletonPatternExample3.cs b/Assets/Creational Patterns/Singleton Pattern/Example3/SingletonPatternExample3.cs index 7774d02..bada85a 100644 --- a/Assets/Creational Patterns/Singleton Pattern/Example3/SingletonPatternExample3.cs +++ b/Assets/Creational Patterns/Singleton Pattern/Example3/SingletonPatternExample3.cs @@ -7,28 +7,19 @@ namespace SingletonPatternExample3 { - public class SingletonPatternExample3 : MonoBehaviour { void Start() { - //单例A SingletonA.Instance.DoSomething(); - - //单例B SingletonB.Instance.DoSomething(); } - } - /// - /// 单例类基类(抽象类、泛型,其他类只需继承此类即可成为单例类) - /// 继承该类的,即成为一个单例类 - /// - public abstract class Singleton - where T : class, new() + public abstract class Singleton where T : class, new() { - private static T _instance = null; + private static readonly object _syncLock = new object(); + private static T _instance; public static T Instance { @@ -36,41 +27,32 @@ public static T Instance { if (_instance == null) { - _instance = new T(); - return _instance; + lock (_syncLock) + { + if (_instance == null) + { + _instance = new T(); + } + } } return _instance; } } - - protected virtual void Awake() - { - _instance = this as T; - } } - - /// - /// 继承自Singleton的单例 - /// public class SingletonA : Singleton { public void DoSomething() { - Debug.Log("SingletonA:DoSomething!"); + Debug.Log("SingletonA: DoSomething!"); } } - /// - /// 继承自Singleton的单例 - /// public class SingletonB : Singleton { public void DoSomething() { - Debug.Log("SingletonB:DoSomething!"); + Debug.Log("SingletonB: DoSomething!"); } } - - } \ No newline at end of file diff --git a/Assets/Creational Patterns/Singleton Pattern/Structure/SingletonStructure.cs b/Assets/Creational Patterns/Singleton Pattern/Structure/SingletonStructure.cs index 478c89f..2530a41 100644 --- a/Assets/Creational Patterns/Singleton Pattern/Structure/SingletonStructure.cs +++ b/Assets/Creational Patterns/Singleton Pattern/Structure/SingletonStructure.cs @@ -8,14 +8,11 @@ public class SingletonStructure : MonoBehaviour { - void Start() { - // Constructor is protected -- cannot use new - Singleton s1 = Singleton.Instance(); - Singleton s2 = Singleton.Instance(); + var s1 = Singleton.Instance; + var s2 = Singleton.Instance; - // Test for same instance if (s1 == s2) { Debug.Log("Objects are the same instance"); @@ -23,27 +20,21 @@ void Start() } } -/// -/// The 'Singleton' class -/// -class Singleton +public class Singleton { private static Singleton _instance; - // Constructor is 'protected' - protected Singleton() - { - } + protected Singleton() { } - public static Singleton Instance() + public static Singleton Instance { - // Uses lazy initialization. - // Note: this is not thread safe. - if (_instance == null) + get { - _instance = new Singleton(); + if (_instance == null) + { + _instance = new Singleton(); + } + return _instance; } - - return _instance; } } \ No newline at end of file diff --git a/Unity-Design-Pattern.sln b/Unity-Design-Pattern.sln index 39ac0e6..2ea3f1d 100644 --- a/Unity-Design-Pattern.sln +++ b/Unity-Design-Pattern.sln @@ -1,7 +1,7 @@  -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity-Design-Pattern", "Unity-Design-Pattern.csproj", "{AA5D6718-EC1F-D1EA-526D-52AF3C037FBB}" +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity-Design-Pattern", "Assembly-CSharp.csproj", "{8ABF50DE-5C45-E1BE-2FA5-8FD59671116B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -9,12 +9,15 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AA5D6718-EC1F-D1EA-526D-52AF3C037FBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AA5D6718-EC1F-D1EA-526D-52AF3C037FBB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AA5D6718-EC1F-D1EA-526D-52AF3C037FBB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AA5D6718-EC1F-D1EA-526D-52AF3C037FBB}.Release|Any CPU.Build.0 = Release|Any CPU + {8ABF50DE-5C45-E1BE-2FA5-8FD59671116B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ABF50DE-5C45-E1BE-2FA5-8FD59671116B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ABF50DE-5C45-E1BE-2FA5-8FD59671116B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ABF50DE-5C45-E1BE-2FA5-8FD59671116B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Assembly-CSharp.csproj + EndGlobalSection EndGlobal