文章地址:https://www.cnblogs.com/liangxiegame/p/you-ya-deQSignleton-yi-Singleton-dan-li-shi-xian.html
https://www.cnblogs.com/liangxiegame/p/you-ya-deQSignleton-er-MonoSingleton-dan-li-shi-xi.html
1.一个简单的泛型单例
public abstract class Singleton<T> where T : class, new()
{
private static T m_Instance;
public static T Instance
{
get
{
if (Singleton<T>.m_Instance == null)
{
Singleton<T>.m_Instance = Activator.CreateInstance<T>();
if (Singleton<T>.m_Instance != null)
{
(Singleton<T>.m_Instance as Singleton<T>).Init();
}
}
return Singleton<T>.m_Instance;
}
}
public static void Release()
{
if (Singleton<T>.m_Instance != null)
{
Singleton<T>.m_Instance = null;
}
}
public virtual void Init()
{
}
public abstract void Dispose();
}
需要注意的:泛型约束WhereT:class,new()
这里约束new(),使得原本不可以创建对象的泛型类必须有一个可访问的无参构造函数。便可在此类中使用new T()的方式为泛型类型创建一个对象。Activator.createInstance<T>()这个接口内部实际上也是这个操作,不过他多了一个抛异常的操作
2.MonoSingleton单例
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
private static T mInstance = null;
public static T Instance
{
get
{
if (mInstance == null)
{
mInstance = GameObject.FindObjectOfType(typeof(T)) as T;
if (mInstance == null)
{
GameObject go = new GameObject(typeof(T).Name);
mInstance = go.AddComponent<T>();
GameObject parent = GameObject.Find("Boot");
if (parent == null)
{
parent = new GameObject("Boot");
GameObject.DontDestroyOnLoad(parent);
}
else
{
go.transform.parent = parent.transform;
}
}
}
return mInstance;
}
}
//统一初始化入口
public void Startup()
{
}
private void Awake()
{
if (mInstance == null)
{
mInstance = this as T;
}
DontDestroyOnLoad(gameObject);
Init();
}
protected virtual void Init()
{
}
public void DestroySelf()
{
Dispose();
MonoSingleton<T>.mInstance = null;
UnityEngine.Object.Destroy(gameObject);
}
public virtual void Dispose()
{
}
}
注意:
1.Startup方法:这个方法的作用是统一规范初始化。普通地我们要初始化这个实例之需要调用其中任意一个实例成员便可,但是假如这样就会出现A类用A方法初始化,B类用B方法初始化,会显得很乱,时间久了可能自己都不明白是在哪里做的初始化。所以这里提供了一个没有任何实际操作的方法Startup用来统一初始化入口
2.awake的执行时机,awake是在脚本实例被创建的时候执行的,就是说只要当前这个游戏对象是Enable=true,这里的get中AddComponent的时候就会执行一次awake。并且子类里不要有awake,否则会覆盖掉这里的awake。