简介
有些管理器性质的类,只存在一个就可以.单例模式就是为了保证不多创建这种类,来节省消耗,另外实例是全局变量,让获取也变得方便.
代码
1. 普通单例
这个写法是在<剑指offer>这本书里学到的,有很多中单例的写法有一些缺陷,比如多线程上的,频繁使用对象锁之类的.
最终学习了这种最优最简的单例模式写法
new()这里,我第一次接触的时候也不明白他的作用.
new实际有三种用法,但我们平时只会用它new对象.
另外两种用法,一个是用来隐藏父类的方法.子类继承父类之后,相同的方法名加new关键字可以隐藏父类同名方法
还有一种就是下面的用法,是用来限制这个类一定要有一个参数为空的构造函数
internal关键词使得只有当前类本身可以调用instance变量,static使得instance只会使用一次构造函数
这样instance就是唯一的,且除本类以外不可以调用的类了
泛型的设计使得这个单例成为了一个小模块,封装了单例的功能.只要我们需要单例模式,直接继承就可以
public class BaseSingleTon<T> where T: class ,new() {
public static T Instance {
get {
return Inner.instance;
}
}
class Inner {
internal static readonly T instance = new T();
}
}
2.mono单例
unity有它特有的机制,也就是继承了MonoBehaviour的类,他们无法被new出来,自然无法使用正常的单例模式.我们以物体为载体,写了另一种单例模式
iLock是对象锁,为了保证多线程下也不会重复创建
IsAlive的存在是为了避免一个bug.在Unity的OnDisEable或者OnDestroy里调用单例的时候,可能会导致已经销毁的单例被再次创建.
故我们使用IsAlive判断程序是否即将结束.
public class BaseMonoSingleTon<T> : MonoBehaviour where T : BaseMonoSingleTon<T> ,new(){
private static T instance;//单例
private static object iLock = new object();//对象锁
public static bool IsAlive = true;//避免销毁时创建
public static T Instance
{
get
{
string name = typeof(T).Name;
//查找脚本
var t = FindObjectOfType<T>();
//脚本不存在 创建物体
if (t == null)
{
lock (iLock)
{
if (t == null)
{
if (IsAlive)
{
instance = new GameObject(name).AddComponent<T>();
}
}
}
}
else {
instance = t;
}
return instance;
}
}
private void OnDestroy()
{
IsAlive = false;
}
private void OnApplicationQuit()
{
IsAlive = false;
}
}