单例模式就是保证类的实例的唯一性
一般来说所有的管理类都需要设置为单例模式,音频管理模块,UI管理模块,对象池等 单例模式有各种各样的写法,有很普通的单例模式,有很复杂的单例模式。有的单例模式需要考虑多线程共享的问题,就要进行加锁防止混乱。
单例模式
- 私有静态引用
- 私有构造方法
- 对外暴露的Get方法
一. 普通 非继承Mono单例
最常见,最普通的单例模式基类的写法,使用了泛型进行封装使用。通过static变量和static静态方法,达到程序运行过程中的类实例的唯一性。
public class BaseManager<T> where T : new()
{
private static T instance;
//非必须存在私有构造器,其主要目的是防止 使用new浪费内存
private BaseManager()
{
}
public static T GetInstance()
{
if (instance == null)
instance = new T();
return instance;
}
}
二. 继承MonoBehaviour的脚本的单例模式基类
此种方法存在一个操作上的注意事项,要保证此脚本只挂载在场景中的唯一物体上。否则就会发生浪费内存的情况,因为 instance只能返回最后一个加载脚本的物体的实例。
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T GetInstance()
{
return instance;
}
protected virtual void Awake()
{
instance = this as T;
}
}
三. 继承MonoBehaviour的Auto单例模式基类
此种写法解决了需要保证脚本在场景中挂在的唯一性问题。
/// <summary>
/// 继承了种种自动创建的单例模式基类,不需要我们手动托或者api去加,如果需要使用直接GetInstance就行了
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T GetInstance()
{
//不需要手动拖拽脚本并且 无需检查脚本在场景中的唯一性
if (instance == null)
{
GameObject obj = new GameObject();
//设置对象的名称为脚本的名字
obj.name = typeof(T).ToString();
// 保证切换场景的时候,挂有此脚本的gameobject不被移除。
// 单例模式需要保证程序运行全程都有唯一的实例在运行,存在于整个生命周期之中
instance = obj.AddComponent<T>();
}
return instance;
}
}