简单单例
public class XXXManager
{
private static XXXManager instance = null;
private XXXManager
{
// to do ...
}
public static XXXManager Instance()
{
if (instance == null)
{
instance = new XXXManager();
}
return instance;
}
}
泛型单例
SingletonCreator.cs 专门用来通过反射创建私有构造示例
using System;
using System.Reflection;
public static class SingletonCreator
{
public static T CreateSingleton<T>() where T : class, ISingleton
{
// 获取私有构造函数
var ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
// 获取无参构造函数
var ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);
if (ctor == null)
{
throw new Exception("Non-Public Constructor() not found! in " + typeof(T));
}
// 通过构造函数,常见实例
var retInstance = ctor.Invoke(null) as T;
retInstance.OnSingletonInit();
return retInstance;
}
}
希望在单例类的内部获得初始化事件所以定制了 ISingleton 接口用来接收单例初始化事件。
ISingleton.cs
namespace QFramework
{
public interface ISingleton
{
void OnSingletonInit();
}
}
Singleton.cs
namespace Test
{
public abstract class Singleton<T> : ISingleton where T : Singleton<T>
{
protected static T mInstance;
static object mLock = new object();
protected Singleton()
{
}
public static T Instance
{
get
{
lock (mLock)
{
if (mInstance == null)
{
mInstance = SingletonCreator.CreateSingleton<T>();
}
}
return mInstance;
}
}
public virtual void Dispose()
{
mInstance = null;
}
public virtual void OnSingletonInit()
{
}
}
}
使用
// 1.需要继承 Singleton。
// 2.需要实现非 public 的构造方法。
public class XXXManager : Singleton<XXXManager>
{
private XXXManager()
{
// to do ...
}
}
public static void main(string[] args)
{
XXXManager.Instance.xxxyyyzzz();
}
MonoBehaviour 单例
MonoSingletonProperty.cs
using UnityEngine;
public static class MonoSingletonProperty<T> where T : MonoBehaviour, ISingleton
{
private static T mInstance = null;
public static T Instance
{
get
{
if (null == mInstance)
{
mInstance = MonoSingletonCreator.CreateMonoSingleton<T>();
}
return mInstance;
}
}
public static void Dispose()
{
if (MonoSingletonCreator.IsUnitTestMode)
{
Object.DestroyImmediate(mInstance.gameObject);
}
else
{
Object.Destroy(mInstance.gameObject);
}
mInstance = null;
}
}
MonoSingletonCreator.cs
using System.Reflection;
using UnityEngine;
public static class MonoSingletonCreator
{
public static bool IsUnitTestMode { get; set; }
public static T CreateMonoSingleton<T>() where T : MonoBehaviour, ISingleton
{
T instance = null;
if (!IsUnitTestMode && !Application.isPlaying) return instance;
instance = Object.FindObjectOfType<T>();
if (instance != null)
{
instance.OnSingletonInit();
return instance;
}
MemberInfo info = typeof(T);
var attributes = info.GetCustomAttributes(true);
foreach (var atribute in attributes)
{
var defineAttri = atribute as MonoSingletonPath;
if (defineAttri == null)
{
continue;
}
instance = CreateComponentOnGameObject<T>(defineAttri.PathInHierarchy, true);
break;
}
if (instance == null)
{
var obj = new GameObject(typeof(T).Name);
if (!IsUnitTestMode)
Object.DontDestroyOnLoad(obj);
instance = obj.AddComponent<T>();
}
instance.OnSingletonInit();
return instance;
}
private static T CreateComponentOnGameObject<T>(string path, bool dontDestroy) where T : MonoBehaviour
{
var obj = FindGameObject(path, true, dontDestroy);
if (obj == null)
{
obj = new GameObject("Singleton of " + typeof(T).Name);
if (dontDestroy && !IsUnitTestMode)
{
Object.DontDestroyOnLoad(obj);
}
}
return obj.AddComponent<T>();
}
private static GameObject FindGameObject(string path, bool build, bool dontDestroy)
{
if (string.IsNullOrEmpty(path))
{
return null;
}
var subPath = path.Split('/');
if (subPath == null || subPath.Length == 0)
{
return null;
}
return FindGameObject(null, subPath, 0, build, dontDestroy);
}
private static GameObject FindGameObject(GameObject root, string[] subPath, int index, bool build, bool dontDestroy)
{
GameObject client = null;
if (root == null)
{
client = GameObject.Find(subPath[index]);
}
else
{
var child = root.transform.Find(subPath[index]);
if (child != null)
{
client = child.gameObject;
}
}
if (client == null)
{
if (build)
{
client = new GameObject(subPath[index]);
if (root != null)
{
client.transform.SetParent(root.transform);
}
if (dontDestroy && index == 0 && !IsUnitTestMode)
{
GameObject.DontDestroyOnLoad(client);
}
}
}
if (client == null)
{
return null;
}
return ++index == subPath.Length ? client : FindGameObject(client, subPath, index, build, dontDestroy);
}
使用
public class DataManger : MonoBehaviour, ISingleton
{
public static DataManger Instance
{
get
{
return MonoSingletonProperty<DataManger>.Instance;
}
}
public void OnSingletonInit()
{
}
}