在之前的PlaneSpritesModel中,我们让它继承了IInit接口,单独继承这个接口就表示此脚本的生命周期由生命周期管理器管理。
LifeCycleMgr 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 using System;using System.Collections;using System.Collections.Generic;public class LifeCycleMgr : LazyMonoSing <LifeCycleMgr >, IInit { private enum LifeName { INIT, UPDATE } private readonly ArrayList _objects; private static readonly Dictionary<LifeName,ILifeCycle> _lifeCycles = new () { { LifeName.INIT, new LifeCycle<IInit>() }, { LifeName.UPDATE, new LifeCycle<IUpdate>() } }; private readonly Dictionary<LifeName, Action> _lifeCyclesFuncs = new () { { LifeName.INIT, ()=> { _lifeCycles[LifeName.INIT].Execute((IInit o) => { o.Init(); }); } }, { LifeName.UPDATE, ()=> { _lifeCycles[LifeName.UPDATE].Execute((IUpdate o) => { o.UpdateFun(); }); } } }; void IInit.Init() { Add(); InitObject(); _lifeCyclesFuncs[LifeName.INIT].Invoke(); } private void Add () { _objects.Add(PlaneSpritesModel.Instance); } private void InitObject () { foreach (var obj in _objects) { foreach (var life in _lifeCycles) { if (life.Value.Add(obj)) break ; } } } private void Update () { _lifeCyclesFuncs[LifeName.UPDATE].Invoke(); } } public interface ILifeCycle { bool Add (object obj ) ; void Remove (object obj ) ; void Execute <T >(Action<T> action ) ; } public class LifeCycle <T > : ILifeCycle { private readonly HashSet<object > _objects = new (); private readonly HashSet<object > _objToRemove = new (); public bool Add (object obj ) { if (obj is T) { _objects.Add(obj); return true ; } return false ; } public void Remove (object obj ) { _objToRemove.Add(obj); } public void Execute <T1 >(Action<T1> action ) { foreach (var o in _objects) { if (o == null ) _objToRemove.Add(o); else { if (o is T1 t1) action.Invoke(t1); } } foreach (var o in _objToRemove) { _objects.Remove(o); } _objToRemove.Clear(); } }
这里显式实现了IInit接口,防止外部调用初始化方法。
使用LifeCycle<T>泛型类来作为所有生命周期接口的“容器”,这个类可以理解成一个“配置类”。
使用ILifeCycle接口来抽象化所有生命周期接口和生命周期执行方法 ,这也是尽量修改配置不修改逻辑的思想:
LifeCycleMgr的InitObject方法只需要调用统一的接口方法Add就可以实现自动判断生命周期接口类型并缓存好。
LifeCycleMgr的Init方法和Update方法只需要调用提前配置好的_lifeCyclesFuncs字典里引用的方法即可。
在ILifeCycle之中声明了Execute<T>(Action<T> action)方法,这是一个带有回调的方法,每一个LifeCycle配置类都会执行这个回调方法,回调方法是一个泛型方法,我们把生命周期接口作为泛型参数,在传入的回调方法中把生命周期方法执行掉。这个传入的回调方法是在_lifeCyclesFuncs字典里传入的。
这种思想要体会。
LifeCycleConfig 在Config文件夹内新建LifeCycleConfig文件,把LifeCycleMgr里面配置部分转移到这里
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 using System.Collections.Generic;using System;public class LifeCycleConfig { public static readonly Dictionary<LifeName, ILifeCycle> LifeCycles = new () { { LifeName.INIT, new LifeCycle<IInit>() }, { LifeName.UPDATE, new LifeCycle<IUpdate>() } }; public static readonly Dictionary<LifeName, Action> LifeCyclesFuncs = new () { { LifeName.INIT, ()=> { LifeCycles[LifeName.INIT].Execute((IInit o) => { o.Init(); }); } }, { LifeName.UPDATE, ()=> { LifeCycles[LifeName.UPDATE].Execute((IUpdate o) => { o.UpdateFun(); }); } } }; } public enum LifeName{ INIT, UPDATE }
LifeCycleAddConfig 在Config文件夹内新建LifeCycleAddConfig文件,把LifeCycleMgr里面Add方法内需要添加各个Model的部分转移到这里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System.Collections;public class LifeCycleAddConfig : IInit { public ArrayList Objects { get ; private set ; } public void Init () { Objects = new ArrayList(); Add(); } private void Add () { Objects.Add(PlaneSpritesModel.Instance); } }
拆分后的LifeCycleMgr 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 using System;using System.Collections.Generic;public class LifeCycleMgr : LazyMonoSing <LifeCycleMgr >, IInit { void IInit.Init() { LifeCycleAddConfig lifeCycleAddConfig = new (); lifeCycleAddConfig.Init(); InitObject(lifeCycleAddConfig); LifeCycleConfig.LifeCyclesFuncs[LifeName.INIT].Invoke(); } private void InitObject (LifeCycleAddConfig config ) { foreach (var obj in config.Objects) { foreach (var life in LifeCycleConfig.LifeCycles) { if (life.Value.Add(obj)) break ; } } } public void Add (LifeName lifeName, object obj ) { LifeCycleConfig.LifeCycles[lifeName].Add(obj); } public void Remove (LifeName lifeName, object obj ) { LifeCycleConfig.LifeCycles[lifeName].Remove(obj); } public void RemoveAll (object obj ) { foreach (var life in LifeCycleConfig.LifeCycles) { life.Value.Remove(obj); } } private void Update () { LifeCycleConfig.LifeCyclesFuncs[LifeName.UPDATE].Invoke(); } } public interface ILifeCycle { bool Add (object obj ) ; void Remove (object obj ) ; void Execute <T >(Action<T> action ) ; } public class LifeCycle <T > : ILifeCycle { private readonly HashSet<object > _objects = new (); private readonly HashSet<object > _objToRemove = new (); public bool Add (object obj ) { if (obj is T) { _objects.Add(obj); return true ; } return false ; } public void Remove (object obj ) { _objToRemove.Add(obj); } public void Execute <T1 >(Action<T1> action ) { foreach (var o in _objects) { if (o == null ) _objToRemove.Add(o); else { if (o is T1 t1) action.Invoke(t1); } } foreach (var o in _objToRemove) { _objects.Remove(o); } _objToRemove.Clear(); } }
尽量让每个类都只有单一的职责 通过以上的拆分,让生命周期函数更加灵活可配置。这种思想就是把需要配置的变量拆分成各个单独的类。一些明确需要长期存在的变量在单独的类中声明成静态的(上面的LifeCycleConfig的字典),一些临时的功能性的变量在单独的类中作为普通变量即可(上面LifeCycleAddConfig的Objects变量)。
修改各个Manager 有了LifeCycleMgr之后,我们把其他Manager的生命周期管理放到LifeCycleMgr中
ConfigMgr 让它继承IInit接口
1 public class ConfigMgr : NormalSingleton <ConfigMgr >, IInit
InitCustomAttributes 让它继承IInit接口
1 public class InitCustomAttributes : IInit
修改GameRoot 将GameRoot初始化的逻辑进行转移
1 2 3 4 5 6 7 8 9 10 11 12 using UnityEngine;public class GameRoot : MonoBehaviour { public GameObject canvas; private void Start () { IInit lifeCycle = LifeCycleMgr.Instance; lifeCycle.Init(); UIMgr.Instance.Show(Path.START_VIEW); } }
将转移的逻辑放到LifeCycleAddConfig中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System.Collections;public class LifeCycleAddConfig : IInit { public ArrayList Objects { get ; private set ; } public void Init () { Objects = new ArrayList(); Add(); } private void Add () { Objects.Add(ConfigMgr.Instance); Objects.Add(new InitCustomAttributes()); Objects.Add(PlaneSpritesModel.Instance); } }
如果想要单独指定每个模块初始化的优先级,可以这样修改(伪代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using System.Collections;using System.Collections.Generic;public class LifeCycleAddConfig : IInit { public Dictionary<int ,ArrayList> Objects { get ; private set ; } public void Init () { } private void Add (int priority ) { } }
字典的key值为优先级,Add方法将优先级作为参数,添加到相应的字典,然后再在LifeCycleMgr中根据不同的优先级进行初始化,此处略
修改LifeCycle<T> 在后期的开发中,我们发现使用HashSet<object>在遍历时无法再对集合进行增减操作,这导致对象池中的对象管理总是报错。所以我们还是使用List代替HashSet。
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 public class LifeCycle <T > : ILifeCycle { private readonly List<object > _objects = new (128 ); public bool Add (object obj ) { if (obj is T) { if (_objects.Contains(obj)) return false ; else { _objects.Add(obj); return true ; } } return false ; } public void Remove (object obj ) { _objects.Remove(obj); } public void Execute <T1 >(Action<T1> action ) { for (int i = 0 ; i < _objects.Count; i++) { if (_objects[i] is T1 t1) action.Invoke(t1); } } }