SingletonKit.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /****************************************************************************
  2. * Copyright (c) 2017 ~ 2021 liangxie MIT License
  3. *
  4. * https://github.com/liangxiegame/SingletonKit
  5. ****************************************************************************/
  6. using System;
  7. using System.Reflection;
  8. using UnityEngine;
  9. namespace QFramework
  10. {
  11. /// <summary>
  12. /// 单例接口
  13. /// </summary>
  14. public interface ISingleton
  15. {
  16. /// <summary>
  17. /// 单例初始化(继承当前接口的类都需要实现该方法)
  18. /// </summary>
  19. void OnSingletonInit();
  20. }
  21. /// <summary>
  22. /// 普通类的单例
  23. /// </summary>
  24. /// <typeparam name="T"></typeparam>
  25. public abstract class Singleton<T> : ISingleton where T : Singleton<T>
  26. {
  27. /// <summary>
  28. /// 静态实例
  29. /// </summary>
  30. protected static T mInstance;
  31. /// <summary>
  32. /// 标签锁:确保当一个线程位于代码的临界区时,另一个线程不进入临界区。
  33. /// 如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放
  34. /// </summary>
  35. static object mLock = new object();
  36. /// <summary>
  37. /// 静态属性
  38. /// </summary>
  39. public static T Instance
  40. {
  41. get
  42. {
  43. lock (mLock)
  44. {
  45. if (mInstance == null)
  46. {
  47. mInstance = SingletonCreator.CreateSingleton<T>();
  48. }
  49. }
  50. return mInstance;
  51. }
  52. }
  53. /// <summary>
  54. /// 资源释放
  55. /// </summary>
  56. public virtual void Dispose()
  57. {
  58. mInstance = null;
  59. }
  60. /// <summary>
  61. /// 单例初始化方法
  62. /// </summary>
  63. public virtual void OnSingletonInit()
  64. {
  65. }
  66. }
  67. /// <summary>
  68. /// 属性单例类
  69. /// </summary>
  70. /// <typeparam name="T"></typeparam>
  71. public static class SingletonProperty<T> where T : class, ISingleton
  72. {
  73. /// <summary>
  74. /// 静态实例
  75. /// </summary>
  76. private static T mInstance;
  77. /// <summary>
  78. /// 标签锁
  79. /// </summary>
  80. private static readonly object mLock = new object();
  81. /// <summary>
  82. /// 静态属性
  83. /// </summary>
  84. public static T Instance
  85. {
  86. get
  87. {
  88. lock (mLock)
  89. {
  90. if (mInstance == null)
  91. {
  92. mInstance = SingletonCreator.CreateSingleton<T>();
  93. }
  94. }
  95. return mInstance;
  96. }
  97. }
  98. /// <summary>
  99. /// 资源释放
  100. /// </summary>
  101. public static void Dispose()
  102. {
  103. mInstance = null;
  104. }
  105. }
  106. /// <summary>
  107. /// 普通单例创建类
  108. /// </summary>
  109. internal static class SingletonCreator
  110. {
  111. static T CreateNonPublicConstructorObject<T>() where T : class
  112. {
  113. var type = typeof(T);
  114. // 获取私有构造函数
  115. var constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
  116. // 获取无参构造函数
  117. var ctor = Array.Find(constructorInfos, c => c.GetParameters().Length == 0);
  118. if (ctor == null)
  119. {
  120. throw new Exception("Non-Public Constructor() not found! in " + type);
  121. }
  122. return ctor.Invoke(null) as T;
  123. }
  124. public static T CreateSingleton<T>() where T : class, ISingleton
  125. {
  126. var type = typeof(T);
  127. var monoBehaviourType = typeof(MonoBehaviour);
  128. if (monoBehaviourType.IsAssignableFrom(type))
  129. {
  130. return CreateMonoSingleton<T>();
  131. }
  132. else
  133. {
  134. var instance = CreateNonPublicConstructorObject<T>();
  135. instance.OnSingletonInit();
  136. return instance;
  137. }
  138. }
  139. /// <summary>
  140. /// 单元测试模式 标签
  141. /// </summary>
  142. public static bool IsUnitTestMode { get; set; }
  143. /// <summary>
  144. /// 查找Obj(一个嵌套查找Obj的过程)
  145. /// </summary>
  146. /// <param name="root">父节点</param>
  147. /// <param name="subPath">拆分后的路径节点</param>
  148. /// <param name="index">下标</param>
  149. /// <param name="build">true</param>
  150. /// <param name="dontDestroy">不要销毁 标签</param>
  151. /// <returns></returns>
  152. private static GameObject FindGameObject(GameObject root, string[] subPath, int index, bool build,
  153. bool dontDestroy)
  154. {
  155. GameObject client = null;
  156. if (root == null)
  157. {
  158. client = GameObject.Find(subPath[index]);
  159. }
  160. else
  161. {
  162. var child = root.transform.Find(subPath[index]);
  163. if (child != null)
  164. {
  165. client = child.gameObject;
  166. }
  167. }
  168. if (client == null)
  169. {
  170. if (build)
  171. {
  172. client = new GameObject(subPath[index]);
  173. if (root != null)
  174. {
  175. client.transform.SetParent(root.transform);
  176. }
  177. if (dontDestroy && index == 0 && !IsUnitTestMode)
  178. {
  179. GameObject.DontDestroyOnLoad(client);
  180. }
  181. }
  182. }
  183. if (client == null)
  184. {
  185. return null;
  186. }
  187. return ++index == subPath.Length ? client : FindGameObject(client, subPath, index, build, dontDestroy);
  188. }
  189. /// <summary>
  190. /// 泛型方法:创建MonoBehaviour单例
  191. /// </summary>
  192. /// <typeparam name="T"></typeparam>
  193. /// <returns></returns>
  194. public static T CreateMonoSingleton<T>() where T : class, ISingleton
  195. {
  196. T instance = null;
  197. var type = typeof(T);
  198. //判断T实例存在的条件是否满足
  199. if (!IsUnitTestMode && !Application.isPlaying)
  200. return instance;
  201. //判断当前场景中是否存在T实例
  202. instance = UnityEngine.Object.FindObjectOfType(type) as T;
  203. if (instance != null)
  204. {
  205. instance.OnSingletonInit();
  206. return instance;
  207. }
  208. //MemberInfo:获取有关成员属性的信息并提供对成员元数据的访问
  209. MemberInfo info = typeof(T);
  210. //获取T类型 自定义属性,并找到相关路径属性,利用该属性创建T实例
  211. var attributes = info.GetCustomAttributes(true);
  212. foreach (var atribute in attributes)
  213. {
  214. var defineAttri = atribute as MonoSingletonPath;
  215. if (defineAttri == null)
  216. {
  217. continue;
  218. }
  219. instance = CreateComponentOnGameObject<T>(defineAttri.PathInHierarchy, true);
  220. break;
  221. }
  222. //如果还是无法找到instance 则主动去创建同名Obj 并挂载相关脚本 组件
  223. if (instance == null)
  224. {
  225. var obj = new GameObject(typeof(T).Name);
  226. if (!IsUnitTestMode)
  227. UnityEngine.Object.DontDestroyOnLoad(obj);
  228. instance = obj.AddComponent(typeof(T)) as T;
  229. }
  230. instance.OnSingletonInit();
  231. return instance;
  232. }
  233. /// <summary>
  234. /// 在GameObject上创建T组件(脚本)
  235. /// </summary>
  236. /// <typeparam name="T"></typeparam>
  237. /// <param name="path">路径(应该就是Hierarchy下的树结构路径)</param>
  238. /// <param name="dontDestroy">不要销毁 标签</param>
  239. /// <returns></returns>
  240. private static T CreateComponentOnGameObject<T>(string path, bool dontDestroy) where T : class
  241. {
  242. var obj = FindGameObject(path, true, dontDestroy);
  243. if (obj == null)
  244. {
  245. obj = new GameObject("Singleton of " + typeof(T).Name);
  246. if (dontDestroy && !IsUnitTestMode)
  247. {
  248. UnityEngine.Object.DontDestroyOnLoad(obj);
  249. }
  250. }
  251. return obj.AddComponent(typeof(T)) as T;
  252. }
  253. /// <summary>
  254. /// 查找Obj(对于路径 进行拆分)
  255. /// </summary>
  256. /// <param name="path">路径</param>
  257. /// <param name="build">true</param>
  258. /// <param name="dontDestroy">不要销毁 标签</param>
  259. /// <returns></returns>
  260. private static GameObject FindGameObject(string path, bool build, bool dontDestroy)
  261. {
  262. if (string.IsNullOrEmpty(path))
  263. {
  264. return null;
  265. }
  266. var subPath = path.Split('/');
  267. if (subPath == null || subPath.Length == 0)
  268. {
  269. return null;
  270. }
  271. return FindGameObject(null, subPath, 0, build, dontDestroy);
  272. }
  273. }
  274. /// <summary>
  275. /// 静态类:MonoBehaviour类的单例
  276. /// 泛型类:Where约束表示T类型必须继承MonoSingleton<T>
  277. /// </summary>
  278. /// <typeparam name="T"></typeparam>
  279. public abstract class MonoSingleton<T> : MonoBehaviour, ISingleton where T : MonoSingleton<T>
  280. {
  281. /// <summary>
  282. /// 静态实例
  283. /// </summary>
  284. protected static T mInstance;
  285. /// <summary>
  286. /// 静态属性:封装相关实例对象
  287. /// </summary>
  288. public static T Instance
  289. {
  290. get
  291. {
  292. if (mInstance == null && !mOnApplicationQuit)
  293. {
  294. mInstance = SingletonCreator.CreateMonoSingleton<T>();
  295. }
  296. return mInstance;
  297. }
  298. }
  299. /// <summary>
  300. /// 实现接口的单例初始化
  301. /// </summary>
  302. public virtual void OnSingletonInit()
  303. {
  304. }
  305. /// <summary>
  306. /// 资源释放
  307. /// </summary>
  308. public virtual void Dispose()
  309. {
  310. if (SingletonCreator.IsUnitTestMode)
  311. {
  312. var curTrans = transform;
  313. do
  314. {
  315. var parent = curTrans.parent;
  316. DestroyImmediate(curTrans.gameObject);
  317. curTrans = parent;
  318. } while (curTrans != null);
  319. mInstance = null;
  320. }
  321. else
  322. {
  323. Destroy(gameObject);
  324. }
  325. }
  326. /// <summary>
  327. /// 当前应用程序是否结束 标签
  328. /// </summary>
  329. protected static bool mOnApplicationQuit = false;
  330. /// <summary>
  331. /// 应用程序退出:释放当前对象并销毁相关GameObject
  332. /// </summary>
  333. protected virtual void OnApplicationQuit()
  334. {
  335. mOnApplicationQuit = true;
  336. if (mInstance == null) return;
  337. Destroy(mInstance.gameObject);
  338. mInstance = null;
  339. }
  340. /// <summary>
  341. /// 释放当前对象
  342. /// </summary>
  343. protected virtual void OnDestroy()
  344. {
  345. mInstance = null;
  346. }
  347. /// <summary>
  348. /// 判断当前应用程序是否退出
  349. /// </summary>
  350. public static bool IsApplicationQuit
  351. {
  352. get { return mOnApplicationQuit; }
  353. }
  354. }
  355. /// <summary>
  356. /// MonoSingleton路径
  357. /// </summary>
  358. [AttributeUsage(AttributeTargets.Class)] //这个特性只能标记在Class上
  359. public class MonoSingletonPath : Attribute
  360. {
  361. private string mPathInHierarchy;
  362. public MonoSingletonPath(string pathInHierarchy)
  363. {
  364. mPathInHierarchy = pathInHierarchy;
  365. }
  366. public string PathInHierarchy
  367. {
  368. get { return mPathInHierarchy; }
  369. }
  370. }
  371. /// <summary>
  372. /// 继承Mono的属性单例?
  373. /// </summary>
  374. /// <typeparam name="T"></typeparam>
  375. public static class MonoSingletonProperty<T> where T : MonoBehaviour, ISingleton
  376. {
  377. private static T mInstance;
  378. public static T Instance
  379. {
  380. get
  381. {
  382. if (null == mInstance)
  383. {
  384. mInstance = SingletonCreator.CreateMonoSingleton<T>();
  385. }
  386. return mInstance;
  387. }
  388. }
  389. public static void Dispose()
  390. {
  391. if (SingletonCreator.IsUnitTestMode)
  392. {
  393. UnityEngine.Object.DestroyImmediate(mInstance.gameObject);
  394. }
  395. else
  396. {
  397. UnityEngine.Object.Destroy(mInstance.gameObject);
  398. }
  399. mInstance = null;
  400. }
  401. }
  402. /// <summary>
  403. /// 如果跳转到新的场景里已经有了实例,则不创建新的单例(或者创建新的单例后会销毁掉新的单例)
  404. /// </summary>
  405. /// <typeparam name="T"></typeparam>
  406. public abstract class PersistentMonoSingleton<T> : MonoBehaviour where T : Component
  407. {
  408. protected static T mInstance;
  409. protected bool mEnabled;
  410. /// <summary>
  411. /// Singleton design pattern
  412. /// </summary>
  413. /// <value>The instance.</value>
  414. public static T Instance
  415. {
  416. get
  417. {
  418. if (mInstance == null)
  419. {
  420. mInstance = FindObjectOfType<T>();
  421. if (mInstance == null)
  422. {
  423. var obj = new GameObject();
  424. mInstance = obj.AddComponent<T>();
  425. }
  426. }
  427. return mInstance;
  428. }
  429. }
  430. /// <summary>
  431. /// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it.
  432. /// </summary>
  433. protected virtual void Awake()
  434. {
  435. if (!Application.isPlaying)
  436. {
  437. return;
  438. }
  439. if (mInstance == null)
  440. {
  441. //If I am the first instance, make me the Singleton
  442. mInstance = this as T;
  443. DontDestroyOnLoad(transform.gameObject);
  444. mEnabled = true;
  445. }
  446. else
  447. {
  448. //If a Singleton already exists and you find
  449. //another reference in scene, destroy it!
  450. if (this != mInstance)
  451. {
  452. Destroy(this.gameObject);
  453. }
  454. }
  455. }
  456. }
  457. /// <summary>
  458. /// 如果跳转到新的场景里已经有了实例,则删除已有示例,再创建新的实例
  459. /// </summary>
  460. /// <typeparam name="T"></typeparam>
  461. public class ReplaceableMonoSingleton<T> : MonoBehaviour where T : Component
  462. {
  463. protected static T mInstance;
  464. public float InitializationTime;
  465. /// <summary>
  466. /// Singleton design pattern
  467. /// </summary>
  468. /// <value>The instance.</value>
  469. public static T Instance
  470. {
  471. get
  472. {
  473. if (mInstance == null)
  474. {
  475. mInstance = FindObjectOfType<T>();
  476. if (mInstance == null)
  477. {
  478. GameObject obj = new GameObject();
  479. obj.hideFlags = HideFlags.HideAndDontSave;
  480. mInstance = obj.AddComponent<T>();
  481. }
  482. }
  483. return mInstance;
  484. }
  485. }
  486. /// <summary>
  487. /// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it.
  488. /// </summary>
  489. protected virtual void Awake()
  490. {
  491. if (!Application.isPlaying)
  492. {
  493. return;
  494. }
  495. InitializationTime = Time.time;
  496. DontDestroyOnLoad(this.gameObject);
  497. // we check for existing objects of the same type
  498. T[] check = FindObjectsOfType<T>();
  499. foreach (T searched in check)
  500. {
  501. if (searched != this)
  502. {
  503. // if we find another object of the same type (not this), and if it's older than our current object, we destroy it.
  504. if (searched.GetComponent<ReplaceableMonoSingleton<T>>().InitializationTime < InitializationTime)
  505. {
  506. Destroy(searched.gameObject);
  507. }
  508. }
  509. }
  510. if (mInstance == null)
  511. {
  512. mInstance = this as T;
  513. }
  514. }
  515. }
  516. }