统一使用单例的最佳方法[关闭]

2024-04-23

我想知道哪种是使用单例实例的正确方法:当我创建一个名为“Manager”的单例类并且它包含一个名为“value”的 int 变量并且我有另一个名为“A”的类时...

    //singleton class
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class Manager : MonoBehaviour {
        public static Manager Instance{ set; get;}
        public int value;
        private void Awake () {
            if (Instance == null) {
                Instance = this;
                DontDestroyOnLoad (this.gameObject);
            } else {
                Destroy (gameObject);
            }
        }
    }

所以在我的 A 类中,我可以像这样创建一个单例实例: // 伪代码示例 公共A类 {

        // First
        // using as a global variable
        Manager manager;

        //------------------------------------

        Public void tstOne(){
             // First
             // using that global variable
             manager.Instance.value = 0;

             // Second
             // or this way
             Manager.Instance.value = 0; 
        }
        Public void tstTwo(){
             // First
             // using that global variabl
             manager.Instance.value = 1;

             // Second
             // or this way
             Manager.Instance.value = 1; 
        }
    }

所以我的问题是 - 我应该创建一个全局实例,然后像第一个示例一样使用该实例,还是应该使用第二个示例?

它们在内存消耗和效率方面是否相同? 或者还有其他使用单例的方法吗?


我确认 Ruzihm 的答案(我也同意 derHugo 的评论,我个人更喜欢 SO 并在需要时引用它们。比 Singleton 或 DI 直接方法干净得多)。

具体访问实例成员manager.Instance.value速度较慢,并且还需要在堆上进一步分配内存,因此会损害内存使用和速度性能。 (非常小的性能问题,但仍然如此。)

单例还有进一步改进的空间,特别是如果您不需要它从 MonoBehaviour 派生的话。

You can:

  1. 如果您忘记将其添加到场景中,请确保它也已构建
  2. 使其线程安全(通常统一不需要)
  3. 延迟实现(意味着仅在需要时创建它)
  4. 另外,作为一般规则,最好密封单例类以提高性能(当您使用虚拟方法时,再次确实有轻微的改进)

这将是实现(考虑到您使用Manager作为辅助实例和YourManagerMono如果您需要单一行为逻辑:

public class YourManagerMono : MonoBehaviour
{
}

public sealed class Manager
{
    private static readonly Manager instance = new Manager();
    //use a gameobject to relate it in the scene
    private YourManagerMono monoManager;

    public static Manager Instance => instance;

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Manager() {}

    private Manager()
    {
        //find or create a manager
        monoManager = GameObject.FindWithTag("Manager").GetComponent<YourManagerMono>();
        if (monoManager == null)
        {
            monoManager = new GameObject().AddComponent<YourManagerMono>();
            monoManager.gameObject.tag = "Manager";
            Object.DontDestroyOnLoad(monoManager.gameObject);
        }
    }
}

A great 关于单例的文章 https://csharpindepth.com/articles/singletonJon Skeet 的 C# 实现(我使用了实现 4)。

EDIT:
我再次同意 derHugo 的观点(在对此答案的新评论中)。我的示例用于展示一个有趣的前景并提供尽可能多的性能,但如果您只需要仅具有第 1 点和第 3 点的 Monobehaviour,您可以继续使用单例的通用实现 https://wiki.unity3d.com/index.php/Singleton来自Unify Community(只需记住将最终类设置为密封以帮助编译器)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

统一使用单例的最佳方法[关闭] 的相关文章