单例模式就是保证类的实例的唯一性
一般来说所有的管理类都需要设置为单例模式,音频管理模块,UI管理模块,对象池等
单例模式有各种各样的写法,有很普通的单例模式,有很复杂的单例模式。有的单例模式需要考虑多线程共享的问题,就要进行加锁防止混乱。
一. 普通 非继承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; } }