Blink

纸上得来终觉浅,绝知此事要躬行

C#和Unity的单例模板

单例模式是我们在开发中经常用到的设计模式,单例模式使用起来很方便,在C#中我们一般是这样实现单例模式的

using System;

namespace Test
{

    public class Manager
    {
        private static Manager m_Instance = null;
        public static Manager Instance{
            get{
                if(m_Instance == null)
                    m_Instance = new Manager();
                return m_Instance;
            }
        }

        // 构造函数私有化
        private Manager(){}
    }
}

虽然实现起来很简单,没有什么复杂的,如果有很多的类需要设计成单例类,这样就需要写很多的重复代码,如果有一个模板,那就会方便很多,那我们就一起来看看模板是怎么样的吧

C#单例模板

using System;
using System.Reflection;

/// 
/// 单例模板
/// 注意:一定要将构造函数私有化
/// 
/// 需要设为单例的类
public abstract class Singleton where T : Singleton
{
    private static T m_Instance = null;
    private static readonly string m_Lock = "lock";

    public static T Instance
    {
        get
        {
            if(m_Instance == null)
            {
                lock (m_Lock)
                {
                    if(m_Instance == null)
                    {
                        ConstructorInfo[] infos = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
                        ConstructorInfo info = Array.Find(infos, c => c.GetParameters().Length == 0);
                        if (info == null)
                            throw new Exception("没有找到非公共的构造函数!");
                        m_Instance = info.Invoke(null) as T;
                    }
                }
            }
            return m_Instance;
        }
    }
}

这里需要注意的是,在使用模板的时候,一定要将需要实现单例的类构造函数私有化,否则会抛出异常


Unity中的MonoBehaviour单例模板

using UnityEngine;

public class MonoSingleton : MonoBehaviour where T : MonoBehaviour
{
    protected static T m_Instance = null;

    public static T Instance
    {
        get
        {
            if (m_Instance == null)
            {
                m_Instance = FindObjectOfType();
                if (FindObjectsOfType().Length > 1)
                {
                    Debug.LogWarning("More than 1");
                    return m_Instance;
                }
                if (m_Instance == null)
                {
                    var instanceName = typeof(T).Name;
                    var instanceObj = GameObject.Find(instanceName);
                    if (!instanceObj)
                        instanceObj = new GameObject(instanceName);
                    m_Instance = instanceObj.AddComponent();
                    DontDestroyOnLoad(instanceObj); //保证实例不会被释放
                }
            }

            return m_Instance;
        }
    }

    protected virtual void OnDestroy()
    {
        m_Instance = null;
    }
}

使用的时候只要让需要实现单例的类继承单例模板就行了,这样大大的减少了重复性的代码

点赞

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注