统一使用Singleton的最佳方法 [英] Best way to use Singletons in unity
问题描述
我想知道哪种方法是使用单例实例的正确方法:当我创建一个名为"Manager"的单例类,并且它包含一个名为"value"的int变量,而我又有一个名为"A"的类.../p>
//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.
您可以:
- 如果您忘记将其添加到场景中,请确保它也是构建的
- 使其具有线程安全性(通常不需要统一)
- 懒惰地实现它(意味着您仅在需要时创建它)
- 此外,通常最好密封单例类以提高性能(再次使用虚拟方法时确实略有改进)
这将是实现(考虑将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);
}
}
}
Jon Skeet撰写的有关C#的单例实现的很棒的文章(我使用实现4)./p>
So inside my A class I can make a instance of the singleton like this:
// example pseudo code
public class A
{ So my problem is - should I create A global instance and then use that instance like in first one or should I use the second example? Are they both are same in terms of memory consumption and efficiency?
Or is there another way to use singletons? I confirm Ruzihm answer (and I also agree with derHugo comment, I personally prefer SO and reference them where required. Much cleaner than Singleton or DI direct approach). To be specific accessing the instance member There's also further room of improvement on the singleton, especially if you do not require it to derive from MonoBehaviour. You can: This would be the implementation (considering you use the A great article about singleton implementation for C# by Jon Skeet (I used implementation 4). EDIT: 这篇关于统一使用Singleton的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
我再次同意derHugo(在有关此答案的新评论中).我的示例用于显示有趣的预期结果并提供尽可能多的性能,但是如果您只需要具有第1点和第3点的Monohhaviour,则可以继续使用 //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);
}
}
}
// 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;
}
}
manager.Instance.value
is slower and also requires further memory allocation on the heap so it hurts both memory usage and speed performance. (Very small performance issues, but still.)
Manager
as helper instance and YourManagerMono
if you require monobehaviour logic: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);
}
}
}
Again I agree with derHugo (in the new comment on this answer). My example is used to show an interesting prospective and to offer as much performance as I can, but if you just require a Monobehaviour with just point 1 and 3 you may go ahead with a generic implementation of singleton from Unify Community (just remember to set the end class as sealed to help the compiler).