c#通过反射实现单例模式
常见的单例模式为:
不继承MONO:
public class Singleton{
private static Singleton m_instance;
public static Singleton Instance
{
get
{
if (m_instance == null)
{
m_instance = new Singleton();
}
return m_instance;
}
}
private Singleton()
{
}
}
这⾥因为在unity中,对于线程安全那些就不考虑了。必要时加个锁(lock)。注意的两点是
1.防⽌外部再实例化这个类,要把构造函数设置为私有。
2.不继承MONO,可以直接通过new创建单例,如果继承MONO,上述⽅法⽆效,原因在于MONO是依附于GameObject的,不能通过new 直接实例化继承MONO的类。
继承MONO:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class MonoSingleton<T> :MonoBehaviour where T: MonoBehaviour
{
private static T m_instance;
public static T Instance
{
get
{
if (m_instance == null)
{
m_instance = Object.FindObjectOfType<T>();
if (m_instance == null)
{
GameObject obj=new GameObject("MonoSingleton");
m_instance = obj.AddComponent<T>();
Object.DontDestroyOnLoad(obj);
}
}
return m_instance;
}
}
}
上⾯直接写了⼀个继承MONO的泛型类,任何继承MONO的单例直接引⽤这个就可以。下⾯重点介绍不继承MONO的单例写法,与最上⾯基本写法区别在于,不需要在每个单例中都写那么⼀⼤段单例,只需要继承该类即可。
泛型类:Singleton<T>
public abstract class Singleton<T> where T : class, new()
{
protected static T _instance = null;
public static T Instance
{
get
{
if (_instance == null)
{
_instance = new T();
}
return _instance;
}
}
protected Singleton()
{
Init();
}
public virtual void Init()
{
}
}
这种通过泛型的⽅式好处在于继承它的类可以全部以单例去实现,不需要单独再写。但是!!要注意两点:1.必须加上new(),这样才能对它进⾏实例化,不然会报下列错误
2.虽然这样可以省掉每个类中单独去申明变量,但也导致将类的构造函数暴露了出来。
⽐如这⾥你新建了⼀个类继承它,那构造函数就⽆法设置成private,这样就导致单例的不合理性。
⾄此,上⾯的问题暴露出来的问题是
如果每个单例类单独写Instance变量,虽然可以实现构造⽅法私有,但⽐较繁琐。
如果统⼀通过泛型类去做单例,虽然书写简单了很多,但是切导致构造函数暴露。
这也印出来本⽂的重头戏:⽤反射,解决以上两个问题,实现单例的效果
通过反射实现单例:
public abstract class Singleton<T> where T : class
{
private static T m_intance;
public static T Instance
{
get
{
if (null == m_intance)
{
m_intance = null;
Type type = typeof (T);
System.Reflection.ConstructorInfo[] constructorInfoArray =
type.GetConstructors(System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic);
foreach (System.Reflection.ConstructorInfo constructorInfo in constructorInfoArray)
{
System.Reflection.ParameterInfo[] parameterInfoArray = constructorInfo.GetParameters();
if (0 == parameterInfoArray.Length)
{
m_intance = (T) constructorInfo.Invoke(null);
break;
}
}
if (null == m_intance)
{
throw new NotSupportedException("No NonPublic constructor without 0 parameter");
}
}
单例模式的几种实现方式return m_intance;
}
}
protected Singleton()
{
}
public static void Destroy()
{
m_intance = null;
}
}
简单解释⼀下反射的原理,⾸先将类型强转,Type type = typeof (T);然后获取到它的构造函数的类型和参数信息。这⾥做了⼀个监测,如果构造函数是私有或者静态,并且构造函数⽆参,才会进⾏单例的实现。
所以这⾥⽤反射的原因就在于,可以通过反射去调⽤私有的构造函数,实现了构造函数不对外暴露的同时,实现了单例的简化,不需要每个单例类单独书写。
唯⼀的缺点,应该就是这种⽅式⽐较复杂,稍微多了⼀点空间上的内存和⼀丁点性能,可以忽略不计。这⾥引⽤⼀个别⼈对于反射的博客:
⾄此,单例的⼏种模式就介绍完了,个⼈喜欢直接把反射⽅式做成⼀个公共库中的类,每个项⽬直接调⽤就OK。有什么不懂和意见,欢迎留⾔咨询。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论