Unity Singleton単例モードの実現

3211 ワード

従来は以下のブログの一例モデルの実現方法を用いてきた.
Unity Singleton単例クラス(Unity 3 D開発の20)
https://blog.csdn.net/cocos2der/article/details/47335197
今日『剣指Offer』第2版(以下「本の中」と略す)P 32実装単例モードの面接問題2を見てみると、上記の実装は本の中ではよくない解法2であることがわかりました.なぜなら、ロックという比較的時間のかかる操作を使用しているため、実際にはインスタンスの作成後にロック操作を実行する必要はありません.
また、MonoBehaviourを継承していますが、多くの場合、私たちが使用している単例はMonoBehaviourを継承する必要はありません(できるだけ継承しないでください).
ただし、MonoBehaviourを継承するクラスはnewから出られないので、MonoBehaviourを継承したい場合は、本の「強く推奨される解法」をそのまま使用するのではなく、上のブログのように「DontDestroyOnLoad」のGameObjectを生成し、単一のクラスをコンポーネントとして追加するという問題もあります.
OK、次はコードを見てください
一、MonoBehaviourを継承しない単例テンプレート類の作成(本で強く推奨されている解法二を用いた)
PS:もっと簡単な方法はpublic static T Instanceを直接使うことです.では、なぜNest非表示クラスでInstanceを作成するのでしょうか.このインスタンスに静的メソッドがある場合、静的メソッドを呼び出すとpublic static T Instanceを呼び出してインスタンスを作成しますが、実際にはこのクラスの静的メソッドだけではInstanceを作成する必要がなく、メモリを浪費する場合があります.Nest非表示クラスを使用すると、本格的なオンデマンド作成が可能になります.
Singleton.cs
   public class Singleton where T : new()
    {
        public static T Instance
        { 
            get
            {
                return Nested.instance;
            }
        }

        class Nested
        {
            static Nested() { }

            internal static readonly T instance = new T();
        }
    }

単一クラスの作成
    class  SingletonTest:Singleton 
    {
    	// 
    }

使用
SingletonTest.Instance. 

二、MonoBehaviourを継承する単例テンプレートクラスを作成する(上のブログに書いてあるが、本の解法に従ってロックロックの位置を修正し、時間効率を高める)
SingletonForMonoBehaviour.cs
    public class SingletonForMonoBehaviour : MonoBehaviour where T : MonoBehaviour
    {
        private static T _instance;

        private static object _lock = new object();

        public static T Instance
        {
            get
            {
                if (applicationIsQuitting)
                {
                    return null;
                }

                
                if (instance == null)
                {
                    lock (lock)
                    {
                        _instance = (T)FindObjectOfType(typeof(T));


                        if (FindObjectsOfType(typeof(T)).Length > 1)
                        {
                            return _instance;
                        }

                        if (_instance == null)
                        {
                            GameObject singleton = new GameObject();
                            _instance = singleton.AddComponent();
                            singleton.name = "(singleton) " + typeof(T).ToString();

                            DontDestroyOnLoad(singleton);
                        }
                    }
                }
                return _instance;
            }
        }

        private static bool applicationIsQuitting = false;

        public void OnDestroy()
        {
            applicationIsQuitting = true;
        }
    }  

単一クラスの作成
    class  SingletonTest:SingletonForMonoBehaviour 
    {
    	// 
    }

使用
SingletonTest.Instance. 

問題があれば,ご指導を惜しまないでください.