Singleton

本文最后更新于 2026年7月8日 上午

LazySingleton

C#中通用的一种懒加载单例模式实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;

namespace UnityToolkit
{
public class LazySingleton<T> : IDisposable where T : new()
{
private static readonly Lazy<T> s_instance = new Lazy<T>(() =>
{
T t = new T();
if (t is IOnInit init)
{
init.OnInit();
}

return t;
});

public static T Singleton => s_instance.Value;

public virtual void Dispose()
{
if (Singleton is IDisposable disposable)
{
disposable.Dispose();
}
}
}
}

Mono Singleton

Unity下基于MonoBehavior和泛型的单例模式

  • 基于泛型实现
  • 自动清理静态变量,UnityEditor 下可开启选项播放时不重新加载程序集
  • 支持场景和全局单例
  • 支持自动创建
MonoSingleton.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using System;
using UnityEngine;

namespace UnityToolkit
{
public interface IOnlyPlayingModelSingleton
{
}

public interface IAutoCreateSingleton
{
}

public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
private static T _singleton;

protected virtual bool DontDestroyOnLoad()
{
return false;
}

public static T SingletonNullable => _singleton;

public static T Singleton
{
get
{
// 如果T是仅在播放模式下的单例
if (typeof(IOnlyPlayingModelSingleton).IsAssignableFrom(typeof(T)))
{
if (Application.isPlaying == false)
{
return null;
}
}


if (_singleton != null) return _singleton; //第一次访问
_singleton = FindObjectOfType<T>(); // 从场景中查找
if (_singleton != null)
{
_singleton.OnSingletonInit(); //手动初始化
return _singleton;
}

if (typeof(IAutoCreateSingleton).IsAssignableFrom(typeof(T)))
{
GameObject go = new GameObject($"{typeof(T).Name}");
_singleton = go.AddComponent<T>();
_singleton.OnSingletonInit();
return _singleton;
}

throw new NullReferenceException($"Singleton<{typeof(T).Name}>.Singleton -> {typeof(T).Name} is null");
}
}

private void OnSingletonInit()
{
// Debug.Log($"Singleton<{typeof(T).Name}>.OnInit() -> {gameObject.name}");
transform.SetParent(null);
if (DontDestroyOnLoad())
{
DontDestroyOnLoad(gameObject);
}

OnInit();
}


protected virtual void Awake()
{
//Awake时如果还没有被访问 则将自己赋值给_singleton
if (_singleton == null)
{
_singleton = this as T;
// Debug.Log($"Singleton<{typeof(T).Name}>.Awake() -> {gameObject.name}");
_singleton.OnSingletonInit();
return;
}

//如果已经被访问过 则销毁自己
if (_singleton != this)
{
Destroy(gameObject);
}
}

protected virtual void OnInit()
{
}

protected virtual void OnDispose()
{
}

private void OnDestroy()
{
if (_singleton == this)
{
_singleton.OnDispose();
_singleton = null;
}
}


// Unity 2022 后 生命周期变更 OnApplicationQuit -> OnDisable -> OnDestroy
private void OnApplicationQuit()
{
if (_singleton == this)
{
_singleton.OnDispose();
_singleton = null;
}
}

#if UNITY_EDITOR

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
private static void ResetStatic()
{
_singleton = null;
}
#endif
}
}

Singleton
https://nicoier.github.io/2024/06/17/单例/
作者
NicoIer
发布于
2024年6月17日
许可协议