不继承MonoBehaviour单例模式基类

1. 使用不继承MonoBehaviour单例基类的目的

  • 避免重复编写相同的单例模式代码
  • 让项目中的管理器类结构更统一、可维护

2. 缺点

  1. 构造函数问题(必须解决 公共构造函数破坏单例唯一性)
    • 如果单例构造函数未设为 private,外部可能创建多个实例,破坏单例唯一性。需要将单例构造函数设为private,单例基类通过反射创建单例实例,但性能开销较大
  2. 多线程问题(通常不需要解决 Unity 本质是单线程主循环框架,你的管理器一般只在主线程初始化一次,多线程并不会访问到你的单例)
    • 在多线程环境下,如果多个线程同时访问实例创建逻辑,可能导致创建多个实例,需要加锁保证线程安全。
  3. 不推荐使用不继承MonoBehaviour单例基类实现内部物体跨场景,可以使用继承MonoBehaviour单例基类,再把物体拖入Inspect中,UIManager就可以将Canvas拖入

3. 不继承 MonoBehaviour 的单例基类实现(解决构造函数问题)

using System;
using System.Reflection;
using UnityEngine;

/// <summary>
/// 单例模式基类,避免代码冗余
/// </summary>
/// <typeparam name="T"> T:class便于使用反射创建实例 </typeparam>
public abstract class BaseManager<T> where T : class
{
  private static T instance;

  public static T Instance
  {
    get
    {
      if (instance == null)
      {
        //反射创建实例
        // 方法一 通过Activator.CreateInstance创建实例(推荐)
        instance = (T)Activator.CreateInstance(typeof(T), true);

        // 方法二 通过单例私有构造函数创建实例(不推荐)
        //Type type = typeof(T);
        //ConstructorInfo constructor = type.GetConstructor(
        //                               BindingFlags.Instance | BindingFlags.NonPublic,
        //                               null,
        //                              Type.EmptyTypes,
                                       null);
        //if (constructor != null)
        //{
        //  instance = (T)constructor.Invoke(null);
        //}
        //else
        //{
        //  Debug.LogError("没有找到对应的私有构造函数");
        //}
      }
      //返回创建的单例实例
      return instance;
    }
  }
}

4. 不继承 MonoBehaviour 的单例基类实现(解决线程安全问题)

using System;
using System.Reflection;
using UnityEngine;
/// <summary>
/// 单例模式基类 避免代码冗余
/// </summary>
/// <typeparam name="T">继承class类 用于创建实例</typeparam>
public abstract class BaseManager<T> where T : class
{
    private static T instance;

    //用于加锁的对象
    protected static readonly object lockObj = new object();

    //属性的方式
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                    {
                        //通过反射创建实例 
                        //方法一 通过Activator.CreateInstance直接实例化 参数true:允许反射实例化私有构造函数(推荐使用)
                        instance = (T)Activator.CreateInstance(typeof(T), true);

                        //方法二 利用反射获取私有构造函数 通过私有构造函数实例对象(不推荐使用)
                        //Type type = typeof(T);
                        //ConstructorInfo constructor = type.GetConstructor(
                        //    BindingFlags.Instance | BindingFlags.NonPublic, //表示成员私有方法
                        //    null,                                           //表示没有绑定对象
                        //    Type.EmptyTypes,                                //表示没有参数
                        //    null);                                      //表示没有参数修饰符
                        //if (constructor != null)
                        //{
                        //    instance = (T)constructor.Invoke(null);
                        //}
                        //else
                        //{
                        //    Debug.LogError("没有得到相应的私有构造函数");
                        //}
                    }
                }
            }
            return instance;
        }
    }
}
posted @ 2025-12-09 11:22  高山仰止666  阅读(11)  评论(0)    收藏  举报