單例模式 1.個人思路 1.業務需求 統一使用同一個對象(創建的對象為一個 使用的對象是同一個) 2.業務思考 3.實現的方案 2.保證生成的單例唯一 2.1 使用static讓系統幫忙初始化 2.2 使用Unity的生命周期 2.3 使用鎖保證單例唯一 2.4 使用字典保證生成的單例唯一 2.5 ...
單例模式
1.個人思路
- 1.業務需求
統一使用同一個對象(創建的對象為一個 使用的對象是同一個)
- 2.業務思考
- 如何生成對象 保存對象
- 如何保證生成的對象唯一
- 3.實現的方案
- 利用系統在需要用到對象前進行唯一 一次初始化
- 調用對象為空的時候 進行一次初始化 保存對象
2.保證生成的單例唯一
2.1 使用static讓系統幫忙初始化
` public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get { return instance; }
}
}`
2.2 使用Unity的生命周期
` public sealed class Singleton : MonoBehaviour {
public static Singleton Instance { get; private set; }
private void Awake()
{
Instance = this;
}
}`
2.3 使用鎖保證單例唯一
` public sealed class Singleton {
private static Singleton instance = null;
private static readonly Object syuncLock = new Object();
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syuncLock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}`
2.4 使用字典保證生成的單例唯一
`
public sealed class Singleton : ISingleton
{
private Singleton() { }
}
public interface ISingleton {
}
public class SingletonManager
{
private static readonly ConcurrentDictionary<string, ISingleton> singletonDict = new ConcurrentDictionary<string, ISingleton>();
public static T GetSingleton<T>() where T : class, ISingleton
{
string className = typeof(T).ToString();
if (!singletonDict.ContainsKey(className))
{
ConstructorInfo[] constructorInfos = typeof(T).GetConstructors (BindingFlags.Instance | BindingFlags.NonPublic);
ConstructorInfo constructorInfo = Array.Find(constructorInfos, c => c.GetParameters().Length == 0);
if (constructorInfo == null)
{
throw new Exception("生成失敗! 沒有找到私有的構造函數");
}
T manager = constructorInfo.Invoke (null) as T;
singletonDict.TryAdd(className, manager);
}
return singletonDict[className] as T;
}
}`
2.5 綜合考慮
` public class SingletonManager {
private static GameObject singletonManager;
private static readonly object syuncLock = new object();
private static readonly Dictionary<string, ISingleton> singletonDict = new Dictionary<string, ISingleton>();
public static T GetSingleton<T>() where T : class, ISingleton
{
string className = typeof(T).ToString();
if (!singletonDict.ContainsKey(className))
{
lock (syuncLock)
{
if (!singletonDict.ContainsKey(className))
{
T manager = null;
if (typeof(T).IsSubclassOf(typeof(MonoBehaviour)))
{
AddComponentScript<T>(className);
}
else
{
AddScript(className, manager);
}
}
}
}
return singletonDict[className] as T;
}
private static void AddComponentScript<T>(string className)
{
if(singletonManager == null)
{
singletonManager = new GameObject("singletonManager");
UnityEngine.Object.DontDestroyOnLoad(singletonManager);
}
Type type = typeof(T);
singletonManager.AddComponent(type);
singletonDict.Add(className, singletonManager.GetComponent(type) as ISingleton);
}
private static void AddScript<T>(string className, T manager) where T : class, ISingleton
{
ConstructorInfo[] constructorInfos = typeof(T).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
ConstructorInfo constructorInfo = Array.Find(constructorInfos, c => c.GetParameters().Length == 0);
if (constructorInfo == null)
{
throw new Exception("生成失敗! 沒有找到私有的構造函數");
}
manager = constructorInfo.Invoke(null) as T;
singletonDict.Add(className, manager);
}
}`
`public interface ISingleton
{
}`