阅读学习QFramwork中的SingletonKit源码。
作为最常用的单例模块,通过继承单例泛型类来实现,需要私有构造;
//使用第一种接口单例方式
internal class Class2Singleton : Singleton<Class2Singleton>
{
//记录被初始化的次数
private static int mIndex = 0;
//私有构造
private Class2Singleton(){}
public override void OnSingletonInit()
{
mIndex++;
Log(mIndex.ToString());
}
public void Log(string content)
{
Debug.Log("Class2Singleton" + content);
}
}
看一下父类的代码内容,首先是ISingleton接口,方便对单例生命周期进行管理,留有给单例中数据进行初始化操作的方法。
/// <summary>
/// 单例接口
/// </summary>
public interface ISingleton
{
/// <summary>
/// 单例初始化(继承当前接口的类都需要实现该方法)
/// </summary>
void OnSingletonInit();
}
/// <summary>
/// 普通类的单例
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class Singleton<T> : ISingleton where T : Singleton<T>
{
/// <summary>
/// 静态实例
/// </summary>
protected static T mInstance;
/// <summary>
/// 标签锁:确保当一个线程位于代码的临界区时,另一个线程不进入临界区。
/// 如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放
/// </summary>
static object mLock = new object();
/// <summary>
/// 静态属性
/// </summary>
public static T Instance
{
get
{
lock (mLock)
{
if (mInstance == null)
{
//调用单例构造器实例化单例对象
mInstance = SingletonCreator.CreateSingleton<T>();
}
}
return mInstance;
}
}
/// <summary>
/// 资源释放
/// </summary>
public virtual void Dispose()
{
mInstance = null;
}
/// <summary>
/// 单例初始化方法
/// </summary>
public virtual void OnSingletonInit()
{
}
}
其中调用单例构造函数中相关内容:
internal static class SingletonCreator
{
//通过反射来进行对象构造
static T CreateNonPublicConstructorObject<T>() where T : class
{
var type = typeof(T);
// 获取私有构造函数
var constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
// 获取无参构造函数
var ctor = Array.Find(constructorInfos, c => c.GetParameters().Length == 0);
if (ctor == null)
{
throw new Exception("Non-Public Constructor() not found! in " + type);
}
return ctor.Invoke(null) as T;
}
public static T CreateSingleton<T>() where T : class, ISingleton
{
var type = typeof(T);
var monoBehaviourType = typeof(MonoBehaviour);
if (monoBehaviourType.IsAssignableFrom(type))
{
return CreateMonoSingleton<T>();
}
else
{
var instance = CreateNonPublicConstructorObject<T>();
instance.OnSingletonInit();
return instance;
}
}
//······
}
编写案例调用单例;
public class SingletonExample : MonoBehaviour
{
private void Start()
{
Class2Singleton.Instance.Log("我是第一种单例使用方式,第一次使用噢!");
Class2Singleton.Instance.Dispose();
//再次调用
Class2Singleton.Instance.Log("我是第一种单例使用方式,销毁之后,再次使用噢");
}
}
MonoSingleton是继承Mono的单例类型,继承MonoBehaviour类和ISingleton接口,其实现方式与Singleton的内容相似
/// <summary>
/// 静态类:MonoBehaviour类的单例
/// 泛型类:Where约束表示T类型必须继承MonoSingleton<T>
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class MonoSingleton<T> : MonoBehaviour, ISingleton where T : MonoSingleton<T>
{
/// <summary>
/// 静态实例
/// </summary>
protected static T mInstance;
/// <summary>
/// 静态属性:封装相关实例对象
/// </summary>
public static T Instance
{
get
{
if (mInstance == null && !mOnApplicationQuit)
{
mInstance = SingletonCreator.CreateMonoSingleton<T>();
}
return mInstance;
}
}
/// <summary>
/// 实现接口的单例初始化
/// </summary>
public virtual void OnSingletonInit()
{
}
/// <summary>
/// 资源释放
/// </summary>
public virtual void Dispose()
{
if (SingletonCreator.IsUnitTestMode)
{
var curTrans = transform;
//清除单元测试创建的单例对象
do
{
var parent = curTrans.parent;
DestroyImmediate(curTrans.gameObject);
curTrans = parent;
} while (curTrans != null);
mInstance = null;
}
else
{
Destroy(gameObject);
}
}
/// <summary>
/// 当前应用程序是否结束 标签
/// </summary>
protected static bool mOnApplicationQuit = false;
/// <summary>
/// 应用程序退出:释放当前对象并销毁相关GameObject
/// </summary>
protected virtual void OnApplicationQuit()
{
mOnApplicationQuit = true;
if (mInstance == null) return;
Destroy(mInstance.gameObject);
mInstance = null;
}
/// <summary>
/// 释放当前对象
/// </summary>
protected virtual void OnDestroy()
{
mInstance = null;
}
/// <summary>
/// 判断当前应用程序是否退出
/// </summary>
public static bool IsApplicationQuit
{
get { return mOnApplicationQuit; }
}
}
来编写案例来使用Mono单例
namespace QFramework.Example
{
//使用MonoSingletonExample
internal class Class2MonoSingleton : MonoSingleton<Class2MonoSingleton>
{
public override void OnSingletonInit()
{
Debug.Log(name + "---" + "OnSingletonInit");
}
private void Awake()
{
Debug.Log(name + "---" + "awake");
}
private void Start()
{
Debug.Log(name + "---" + "start");
}
protected override void OnDestroy()
{
base.OnDestroy();
Debug.Log(name + "---" + "OnDestroy");
}
}
public class MonoSingletonExample : MonoBehaviour
{
private IEnumerator Start()
{
var instance = Class2MonoSingleton.Instance;
yield return new WaitForSeconds(5.0f);
instance.Dispose();
}
}
}
5s后对单例对象进行释放:
使用MonoSingletonProperty/SingletonProperty两个工具类来封装单例,在实现设置单例类时候不需要再继承 MonoSingleton 或 Singleton ,只需要继承ISingleton接口即可,当然,此处的接口作用就是对该类进行标记说说明,表明类是单例模式。下面看下两个工具类的具体实现:
/// <summary>
/// 属性单例类
/// </summary>
/// <typeparam name="T"></typeparam>
public static class SingletonProperty<T> where T : class, ISingleton
{
/// <summary>
/// 静态实例
/// </summary>
private static T mInstance;
/// <summary>
/// 标签锁
/// </summary>
private static readonly object mLock = new object();
/// <summary>
/// 静态属性
/// </summary>
public static T Instance
{
get
{
lock (mLock)
{
if (mInstance == null)
{
mInstance = SingletonCreator.CreateSingleton<T>();
}
}
return mInstance;
}
}
/// <summary>
/// 资源释放
/// </summary>
public static void Dispose()
{
mInstance = null;
}
}
/// <summary>
/// 继承Mono的属性单例?
/// </summary>
/// <typeparam name="T"></typeparam>
public static class MonoSingletonProperty<T> where T : MonoBehaviour, ISingleton
{
private static T mInstance;
public static T Instance
{
get
{
if (null == mInstance)
{
mInstance = SingletonCreator.CreateMonoSingleton<T>();
}
return mInstance;
}
}
public static void Dispose()
{
if (SingletonCreator.IsUnitTestMode)
{
UnityEngine.Object.DestroyImmediate(mInstance.gameObject);
}
else
{
UnityEngine.Object.Destroy(mInstance.gameObject);
}
mInstance = null;
}
}
internal class Class2SingletonProperty : ISingleton
{
private static int mIndex = 0;
//静态单例属性
public static Class2SingletonProperty Instance
{
get { return SingletonProperty<Class2SingletonProperty>.Instance; }
}
public void OnSingletonInit()
{
mIndex++;
}
private Class2SingletonProperty()
{
}
public void Dispose()
{
SingletonProperty<Class2SingletonProperty>.Dispose();
}
public void Log(string content)
{
Debug.Log("Class2SingletonProperty" + mIndex + "---" + content);
}
}
public class SingletonPropertyExample : MonoBehaviour
{
private void Start()
{
Class2SignetonProperty.Instance.Log("Hello Tony!");
Class2SignetonProperty.Instance.Dispose();
Class2SignetonProperty.Instance.Log("Hello TonyChang");
}
}
其运行结果和第一个单例实现案例结果相同。
internal class Class2MonoSingletonProperty : MonoBehaviour, ISingleton
{
//仅仅需要声明静态属性即可
public static Class2MonoSingletonProperty Instance
{
get { return MonoSingletonProperty<Class2MonoSingletonProperty>.Instance; }
}
//继承ISingleton 接口实现方法
public void OnSingletonInit()
{
Debug.Log(name + "==" + "OnSingletonInit" );
}
public void Dispose()
{
MonoSingletonProperty<Class2MonoSingletonProperty>.Dispose();
}
private void Awake()
{
Debug.Log(name + "==" + "Awake" );
}
private void Start()
{
Debug.Log(name + "==" + "Start" );
}
private void OnDestroy()
{
Debug.Log(name + "==" + "OnDestroy" );
}
}
public class MonoSingletonPropertyExample:MonoBehaviour
{
private IEnumerator Start()
{
var instance = Class2MonoSingletonProperty.Instance;
yield return new WaitForSeconds(5.0f);
instance.Dispose();
}
}
其运行结果和第二个继承Mono的单例实现案例结果相同。
那么不免产生疑问--使用MonoSingletonProperty/SingletonProperty两个工具类来封装单例好处是什么?或者说解决什么问题。
我们看不使用MonoSingletonProperty实现单例,需要继承抽象类MonoSingleton
而使用MonoSingletonProperty之后是继承接口,可以方便继承Mono相关的类。
那么使用ISingleton接口的作用是什么?
作为泛型约束,也就是说想要成为单例的类必须要继承ISingleton接口才可以使用MonoSingletonProperty/SingletonProperty两个工具类。
变相的表明,想要加入单例圈子,需要继承此接口来打个标签。