Singleton dengan jebakan

pengantar


Ada sejumlah besar pola dan antipattern pemrograman. Seringkali penggunaan pola menentukan bagi kita pengalaman dan pengetahuan aktual tentang diri mereka sendiri. Pada artikel ini saya ingin membahas dengan Anda penerapan pola Singleton , yaitu penerapannya di Net sebagaimana diterapkan pada Unity.


Singleton


Saya perhatikan bahwa saya menulis kode dalam sebuah tim, jadi saya mengambil sebanyak mungkin pekerjaan di dalam kode untuk membongkar tim dan menghilangkan kebutuhan untuk memikirkan beberapa kesulitan dalam menerapkan pola-pola tertentu dalam Unity.


Mempelajari literatur di Net 1 , sehubungan dengan pertanyaan ini 2, dan sebagai hasil dari pekerjaan pada beberapa proyek, kelas berikut ini lahir:


using UnityEngine;

/// <summary>
///    .
/// </summary>
/// <typeparam name="T">,    </typeparam>
/// <remarks>
///        OnDestroy  OnApplicationQuit
///      IsAlive.     
/// ,        .
/// 
/// 
///      Awake, OnDestroy, 
/// OnApplicationQuit    
/// base.Awake()  .
/// 
///    Initialization -      
///  .
/// 
///     unity,    
///   .    ,    
///       .
/// 
///  :
///     -  "CLR via C#"
///     - Chris Dickinson "Unity 2017 Game optimization"
///</remarks>

public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{

    private static T instance = null;

    private bool alive = true;

    public static T Instance
    {
        get
        {
            if (instance != null)
            {
                return instance;
            }
            else
            {
                //Find T
                T[] managers = GameObject.FindObjectsOfType<T>();
                if (managers != null)
                {
                    if (managers.Length == 1)
                    {
                        instance = managers[0];
                        DontDestroyOnLoad(instance);
                        return instance;
                    }
                    else
                    {
                        if (managers.Length > 1)
                        {
                            Debug.LogError($"Have more that one {typeof(T).Name} in scene. " +
                                            "But this is Singleton! Check project.");
                            for (int i = 0; i < managers.Length; ++i)
                            {
                                T manager = managers[i];
                                Destroy(manager.gameObject);
                            }
                        }
                    }
                }
                //create 
                GameObject go = new GameObject(typeof(T).Name, typeof(T));
                instance = go.GetComponent<T>();
        instance.Initialization();
                DontDestroyOnLoad(instance.gameObject);
                return instance;
            }
        }

        //Can be initialized externally
        set
        {
            instance = value as T;
        }
    }

    /// <summary>
    /// Check flag if need work from OnDestroy or OnApplicationExit
    /// </summary>
    public static bool IsAlive
    {
        get
        {
            if (instance == null)
                return false;
            return instance.alive;
        }
    }

    protected void Awake()
    {
        if (instance == null)
        {
            DontDestroyOnLoad(gameObject);
            instance = this as T;
            Initialization();
        }
        else
        {
            Debug.LogError($"Have more that one {typeof(T).Name} in scene. " +
                            "But this is Singleton! Check project.");
            DestroyImmediate(this);
        }
    }

    protected void OnDestroy() { alive = false; }

    protected void OnApplicationQuit() { alive = false; }

    protected virtual void Initialization() { }
}

Saya akan fokus pada beberapa aspek.


Penciptaan Obyek


Ketika memperluas proyek, dan bahkan lebih lagi bekerja sebagai tim> 3 orang, situasi sering muncul ketika urutan pembuatan objek menjadi tidak jelas. Sebenarnya 3 , urutan panggilan ke Sedarlah () adalah acak (tentu saja, ini tidak sepenuhnya benar, dan prosesnya dapat dipengaruhi, tetapi dokumentasinya suci), oleh karena itu perlu untuk menghilangkan kelemahan yang mengganggu ini dengan mengimplementasikan properti Instance {get;} . Akibatnya, kami mendapatkan akses penuh ke singleton dari Sedarlah () dari kelas lain.


, Lazy, Awake() .

4-4, , Instance{get;}.



Unity — Awake(). , , Initialization(). (KISS).



, DI SD. . .



, , OnDestroy(), OnApplicationQuit() 5:


Did you spawn new GameObjects from OnDestroy?

, , , . , IsAlive(), , . , ...



Semakin, saya sampai pada kesimpulan bahwa menggunakan paradigma Unity adalah mungkin untuk mengimplementasikan proyek saya tanpa Singleton. Seringkali, menerapkan pola ini membuat kode Anda sangat terhubung dan sangat rapuh.


Terima kasih


Sumber


- Richter J. "CLR via C #. Pemrograman di Microsoft.NET # Framework 4.5 di C #", 2013


- https://www.codingame.com/playgrounds/1979/different-ways-to-implement-singleton-in--net-and-make-people-hate-you-along-the-way


- https://docs.unity3d.com/en/current/ScriptReference/MonoBehaviour.Awake.html


- https://ru.wikipedia.org/wiki/Design_Patterns


- Dickinson Chris "Optimasi Game Unity 2017, Edisi Kedua", 2017


All Articles