Singleton ISingleton 先将重点的ISingleton
接口绘制成UML
代码:
1 2 3 4 5 6 7 8 9 10 public interface ISingleton { void OnSingletonInit () ; }
此图是类图,接口的UML图不是这样的
SingletonCreator 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 internal static class SingletonCreator { static T CreateNonPublicConstructorObject <T >() where T : class { var type = typeof (T); var constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic); var ctor = Array.Find(constructorInfos, c => c.GetParameters().Length == 0 ); if (ctor == null ) { throw new Exception("Non-Public Constructor() not found! in " + type); } return ctor.Invoke(null ) as T; } public static T CreateSingleton <T >() where T : class , ISingleton { var type = typeof (T); var monoBehaviourType = typeof (MonoBehaviour); if (monoBehaviourType.IsAssignableFrom(type)) { return CreateMonoSingleton<T>(); } else { var instance = CreateNonPublicConstructorObject<T>(); instance.OnSingletonInit(); return instance; } } }
SingletonCreator
的职责是,通过反射来确定一个普通单例类是否有私有构造函数,并在其私有构造中获取无参构造,使用这个无参构造实例化普通单例类
Singleton<T> 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 public abstract class Singleton <T > : ISingleton where T : Singleton <T >{ protected static T mInstance; static object mLock = new object (); public static T Instance { get { lock (mLock) { if (mInstance == null ) { mInstance = SingletonCreator.CreateSingleton<T>(); } } return mInstance; } } public virtual void Dispose () { mInstance = null ; } public virtual void OnSingletonInit () { } }
下划线表示静态的。
MonoSingleton CreateMonoSingleton 首先我们查看一下SingletonCreator
里面创建MonoSingleton
的代码:
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 internal static class SingletonCreator { public static T CreateMonoSingleton <T >() where T : class , ISingleton { T instance = null ; var type = typeof (T); if (!IsUnitTestMode && !Application.isPlaying) return instance; instance = UnityEngine.Object.FindObjectOfType(type) as T; if (instance != null ) { instance.OnSingletonInit(); return instance; } MemberInfo info = typeof (T); var attributes = info.GetCustomAttributes(true ); foreach (var atribute in attributes) { var defineAttri = atribute as MonoSingletonPath; if (defineAttri == null ) { continue ; } instance = CreateComponentOnGameObject<T>(defineAttri.PathInHierarchy, true ); break ; } if (instance == null ) { var obj = new GameObject(typeof (T).Name); if (!IsUnitTestMode) UnityEngine.Object.DontDestroyOnLoad(obj); instance = obj.AddComponent(typeof (T)) as T; } instance.OnSingletonInit(); return instance; } }
对应的UML图如下(简化)
MonoSingleton<T> 我们看一下MonoSingleton<T>
泛型类的代码
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 public abstract class MonoSingleton <T > : MonoBehaviour , ISingleton where T : MonoSingleton <T >{ protected static T mInstance; public static T Instance { get { if (mInstance == null && !mOnApplicationQuit) { mInstance = SingletonCreator.CreateMonoSingleton<T>(); } return mInstance; } } public virtual void OnSingletonInit () { } public virtual void Dispose () { if (SingletonCreator.IsUnitTestMode) { var curTrans = transform; do { var parent = curTrans.parent; DestroyImmediate(curTrans.gameObject); curTrans = parent; } while (curTrans != null ); mInstance = null ; } else { Destroy(gameObject); } } protected static bool mOnApplicationQuit = false ; protected virtual void OnApplicationQuit () { mOnApplicationQuit = true ; if (mInstance == null ) return ; Destroy(mInstance.gameObject); mInstance = null ; } protected virtual void OnDestroy () { mInstance = null ; } public static bool IsApplicationQuit { get { return mOnApplicationQuit; } } }
MonoSingleton除了要考虑单例的实现之外,还需要实现一些容错处理,以及一些声明周期查询,比如IsApplicationQuit等。
UML图如下:
SingletonProperty和MonoSingletonProperty 我们在上一节介绍过这两个类的意义。
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 public static class SingletonProperty <T > where T : class , ISingleton { private static T mInstance; private static readonly object mLock = new object (); public static T Instance { get { lock (mLock) { if (mInstance == null ) { mInstance = SingletonCreator.CreateSingleton<T>(); } } return mInstance; } } public static void Dispose () { mInstance = null ; } }
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 public static class MonoSingletonProperty <T > where T : MonoBehaviour , ISingleton { private static T mInstance; public static T Instance { get { if (null == mInstance) { mInstance = SingletonCreator.CreateMonoSingleton<T>(); } return mInstance; } } public static void Dispose () { if (SingletonCreator.IsUnitTestMode) { UnityEngine.Object.DestroyImmediate(mInstance.gameObject); } else { UnityEngine.Object.Destroy(mInstance.gameObject); } mInstance = null ; } }
现在的UML图如下
MonoSingletonPath特性 MonoSingletonPath特性能够让我们创建的Mono单例 按照特性内指定的Hierarchy路径整理好
我们先看一下自定义特性部分的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [AttributeUsage(AttributeTargets.Class) ] public class MonoSingletonPath : Attribute { private string mPathInHierarchy; public MonoSingletonPath (string pathInHierarchy ) { mPathInHierarchy = pathInHierarchy; } public string PathInHierarchy { get { return mPathInHierarchy; } } }
我们在SingletonCreator
的CreateMonoSingleton
方法中通过反射获取应用了这个特性的Mono单例和具体的路径信息
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 internal static class SingletonCreator { private static GameObject FindGameObject (GameObject root, string [] subPath, int index, bool build, bool dontDestroy ) { GameObject client = null ; if (root == null ) { client = GameObject.Find(subPath[index]); } else { var child = root.transform.Find(subPath[index]); if (child != null ) { client = child.gameObject; } } if (client == null ) { if (build) { client = new GameObject(subPath[index]); if (root != null ) { client.transform.SetParent(root.transform); } if (dontDestroy && index == 0 && !IsUnitTestMode) { GameObject.DontDestroyOnLoad(client); } } } if (client == null ) { return null ; } return ++index == subPath.Length ? client : FindGameObject(client, subPath, index, build, dontDestroy); } public static T CreateMonoSingleton <T >() where T : class , ISingleton { MemberInfo info = typeof (T); var attributes = info.GetCustomAttributes(true ); foreach (var atribute in attributes) { var defineAttri = atribute as MonoSingletonPath; if (defineAttri == null ) { continue ; } instance = CreateComponentOnGameObject<T>(defineAttri.PathInHierarchy, true ); break ; } } private static T CreateComponentOnGameObject <T >(string path, bool dontDestroy ) where T : class { var obj = FindGameObject(path, true , dontDestroy); if (obj == null ) { obj = new GameObject("Singleton of " + typeof (T).Name); if (dontDestroy && !IsUnitTestMode) { UnityEngine.Object.DontDestroyOnLoad(obj); } } return obj.AddComponent(typeof (T)) as T; } private static GameObject FindGameObject (string path, bool build, bool dontDestroy ) { if (string .IsNullOrEmpty(path)) { return null ; } var subPath = path.Split('/' ); if (subPath == null || subPath.Length == 0 ) { return null ; } return FindGameObject(null , subPath, 0 , build, dontDestroy); } }
MonoSingletonPath示例 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 using UnityEngine;using QFramework;namespace FrameworkDesign { public class MonoSingletonExample : MonoBehaviour { [MonoSingletonPath("[Logic]/GameManager" ) ] public class GameManager : MonoSingleton <GameManger >{} [MonoSingletonPath("[Framework]/ResManager" ) ] public class ResManager : MonoSingleton <ResManager >{} [MonoSingletonPath("[Framework]/UIManager" ) ] public class UIManager : MonoSingleton <UIManager >{} [MonoSingletonPath("[Framework]/SoundManager" ) ] public class SoundManager : MonoSingleton <SoundManager >{} [MonoSingletonPath("[Logic]/ConfigManager" ) ] public class ConfigManager : MonoSingleton <ConfigManager >{} [MonoSingletonPath("[Logic]/BattleManager" ) ] public class BattleManager : MonoSingleton <BattleManager >{} [MonoSingletonPath("[Framework]/NetworkManager" ) ] public class NetworkManager : MonoSingleton <NetworkManager >{} void Start () { var gameMgr = GameManager.Instance; var resMgr = ResManager.Instance; var uiMgr = UIManager.Instance; var soundMgr = SoundManager.Instance; var configMgr = ConfigManager.Instance; var buttleMgr = BattleManager.Instance; var networkMgr = NetworkManager.Instance; } } }
最终的UML图