Unity中的单例设计模式的实现

1. 最简单的单例

代码简单适合单例很少的项目,非线程安全

public class instance_normal
{
    
    
    // 单例对象
    private static instance_normal instance;
    // 获取单例
    public static instance_normal GetInstance
    {
    
    
        get
        {
    
    
            if (instance == null)
            {
    
    
                instance = Activator.CreateInstance<instance_normal>();
            }
            return instance;
        }
    }

    public void Init()
    {
    
    
        Debug.Log("instance_normal.Init");
    }

    /// <summary>
    /// 首次调用的时候需要实例化
    /// </summary>
    // instance_normal.GetInstance.Init();
}

2. 简单的泛型单例

/// <summary>
/// 代码简单,继承Singleton<T>类就可以继承实现单例类。
/// 因为泛型约束中使用new(),因此子类无法私有化构造函数,子类依然可以通过new来实例化对象。
/// 适合单例使用较多的项目。
/// </summary>
/// <typeparam name="T"></typeparam>
public class Singleton<T> where T : class, new()
{
    
    
    private static T instance = default(T);

    public static T GetInstance()
    {
    
    
        if (instance == null)
        {
    
    
            instance = new T();
        }
        return instance;
    }
}

泛型单例的使用

public class GameManager : Singleton<GameManager>
{
    
    
    /// <summary>
    /// 初始化
    /// </summary>
    public void InitGame()
    {
    
    
        Debug.Log("GameManager.Init");
    }
}

/// <summary>
/// 调用方式
/// </summary>
/// GameManager.GetInstance().InitGame();

3. 静态内部类

静态成员的初始化是在类进行装载的时候进行的,在没有调用过GetSingleton()方法之前InitSingleton_S类没有进行任何调用,所以Singleton_S的单例也没有初始化。

public class Singleton_S
{
    
    
    Singleton_S() {
    
     }

    // 使用静态内部类完成初始化
    private static class InitSingleton_S
    {
    
    
        public static Singleton_S Instance = new Singleton_S();
    }

    // 提供给外界进行调用实例的方法
    public static Singleton_S GetSingleton_S()
    {
    
    
        return InitSingleton_S.Instance;
    }
}

4. 继承自MonoBehaviour的简单单例

需要挂载在场景的GameObject中

public class Singleton_M : MonoBehaviour
{
    
    
    // 创建静态实例
    public static Singleton_M instance;

    // 防止外部进行额外的实例化将构造函数设为private
    private Singleton_M()
    {
    
    

    }

    private void Awake()
    {
    
    
        instance = this;
    }
}

5. 场景中常驻的单例

public class GameMgr : MonoBehaviour
{
    
    
    private static GameMgr instance;

    public static GameMgr GetInstance
    {
    
    
        get
        {
    
    
            if (instance == null)
            {
    
    
                // 新建单例挂在新建Obj上 
                GameObject obj = new GameObject("GameMgrObj");
                instance = obj.AddComponent<GameMgr>();
                // 将挂载单例Obj设为不销毁的对象
                DontDestroyOnLoad(obj);
            }

            return instance;
        }
    }

    public void Init()
    {
    
    
        Debug.Log("GameMgr.Init");
    }
}

6. 单例的销毁

单例如果没有及时销毁,里面对其它类的引用就会一直持有,GC的时候无法回收这部分内存占用,必定造成内存泄漏。所以需要销毁的单例类一定要加入销毁方法。

    public static bool DestoryInstance()
    {
    
    
        if (instance == null)
        {
    
    
            return false;
        }

        instance = null;
        return true;
    }

7. 使用扩展方法代替直接使用单例

例如:
频繁使用的缓存池回收方法,回收方法需要进行其他操作直接在扩展方法里修改就好,不比去一个个修改或者直接修改缓存池的代码。

public static void RecycleObj( this GameObject obj, int count = 1 )
{
    
    
	// 缓存池回收
    PoolManager.instance.RecycleObj( obj, count );
}

Unity的输出方法

public static class Console
{
    
    
    public static void Log(object message, UnityEngine.Object context = null)
    {
    
    
        Debug.Log("<b>Log: </b>" + message, context);
    }

    public static void LogFormat(string format, params object[] args)
    {
    
    
        Debug.LogFormat("<b>Log: </b>" + format, args);
    }
}

猜你喜欢

转载自blog.csdn.net/the_vnas/article/details/126571254