SingletonSystem 单例管理系统

SingletonSystem 单例管理系统

单例模式是项目中最为常见的设计模式之一,但是写法都不够优雅不方便查找和管理,下面介绍一种使用反射实现的单例管理架构,需要基于之前介绍过的AssemblyManager 程序集管理器

1.AssemblyManager

每次加载程序集的时候会有相应的事件回调机制,并且AssemblyManager 提供了遍历程序集中的类或者实现某个接口的类,使用此功能便能实现比较优雅的单例管理系统

2.定义两个接口ISingleton、IUpdateSingleton

public interface ISingleton : IDisposable
{
    
    
    public bool IsDisposed {
    
     get; set; }
    Task Initialize();
}
public interface IUpdateSingleton : ISingleton
{
    
    
    public void Update();
}

3.单例基类Singleton

public abstract class Singleton<T> : ISingleton where T : ISingleton, new()
{
    
    
    public bool IsDisposed {
    
     get; set; }
    public static T Instance {
    
     get; private set; }

    private void RegisterSingleton(ISingleton singleton)
    {
    
    
        Instance = (T)singleton;
        IsDisposed = false;
        AssemblyManager.OnLoadAssemblyEvent += Load;
        AssemblyManager.OnUnLoadAssemblyEvent += UnLoad;
    }

    protected abstract void UnLoad(int assemblyName);

    protected abstract void Load(int assemblyName);

    public virtual Task Initialize()
    {
    
    
        return Task.CompletedTask;
    }
    public virtual void Dispose()
    {
    
    
        IsDisposed = true;
        Instance = default;
        AssemblyManager.OnLoadAssemblyEvent -= Load;
        AssemblyManager.OnUnLoadAssemblyEvent -= UnLoad;
    }
}

4.SingletonSystem单例管理系统

首先用队列存储所有程序集中单例实现Update的接口,便于每帧更新
其次使用多值队列存储某个程序集中所有的单例

    private static readonly Queue<IUpdateSingleton> updateSingletons = new Queue<IUpdateSingleton>();
    private static readonly OneToManyQueue<int, ISingleton> singletons = new OneToManyQueue<int, ISingleton>();

初始化SingletonSystem,需要外界手动调用

    public static void Initialize()
    {
    
    
        AssemblyManager.OnLoadAssemblyEvent += Load;
        AssemblyManager.OnUnLoadAssemblyEvent += UnLoad;
    }

单例系统的释放,需要外界手动调用

    public static void Dispose()
    {
    
    
        foreach (var item in singletons.Values)
        {
    
    
            UnLoad(item);
        }
        updateSingletons.Clear();
        singletons.Clear();
        AssemblyManager.OnLoadAssemblyEvent -= Load;
        AssemblyManager.OnUnLoadAssemblyEvent -= UnLoad;
    }

其余加载卸载

    private static void UnLoad(int assemblyName)
    {
    
    
        if (!singletons.TryGetValue(assemblyName, out var queue))
            return;
        UnLoad(queue);
        singletons.RemoveKey(assemblyName);
    }

    private static void Load(int assemblyName)
    {
    
    
        List<Task> tasks = new List<Task>();
        UnLoad(assemblyName);

        foreach (Type singletonType in AssemblyManager.ForEach(assemblyName,typeof(ISingleton)))
        {
    
    
            var instance = (ISingleton)Activator.CreateInstance(singletonType);
            MethodInfo registerMethodInfo = singletonType.BaseType?.GetMethod("RegisterSingleton", BindingFlags.Instance | BindingFlags.NonPublic);
            MethodInfo initializeMethodInfo = singletonType.GetMethod("Initialize", BindingFlags.Instance | BindingFlags.Public);
            MethodInfo onLoadMethodInfo = singletonType.GetMethod("Load", BindingFlags.Instance | BindingFlags.NonPublic);

            if (initializeMethodInfo != null)
            {
    
    
                tasks.Add((Task)initializeMethodInfo.Invoke(instance, null));
            }
            registerMethodInfo?.Invoke(instance, new object[] {
    
     instance });
            onLoadMethodInfo?.Invoke(instance, new object[] {
    
     assemblyName });

            switch (instance)
            {
    
    
                case IUpdateSingleton updateSingleton:
                    updateSingletons.Enqueue(updateSingleton);
                    break;
                default:
                    break;
            }
            singletons.Enqueue(assemblyName, instance);
        }

        Task.WaitAll(tasks.ToArray());
    }

    public static void Update()
    {
    
    
        int updateCount = updateSingletons.Count;
        while (updateCount-- >0)
        {
    
    
            IUpdateSingleton updateSingleton = updateSingletons.Dequeue();
            if (updateSingleton.IsDisposed)
                continue;
            updateSingletons.Enqueue(updateSingleton);
            try
            {
    
    
                updateSingleton.Update();
            }
            catch (Exception ex)
            {
    
    
                Debug.LogError(ex.Message);
            }
        }
    }

    private static void UnLoad(Queue<ISingleton> queue)
    {
    
    
        if (queue == null)
            return;
        while (queue.Count > 0)
        {
    
    
            try
            {
    
    
                queue.Dequeue().Dispose();
            }
            catch (Exception ex)
            {
    
    
                Debug.LogError(ex.Message);
            }
        }
    }

5.测试

测试单例

public class TestSingleton : Singleton<TestSingleton>,IUpdateSingleton
{
    
    
    public override Task Initialize()
    {
    
    
        Debug.Log("TestSingleton 初始化");
        return base.Initialize();
    }
    protected override void Load(int assemblyName)
    {
    
    
    }

    protected override void UnLoad(int assemblyName)
    {
    
    
        Debug.Log("卸载!");
    }

    public void TestFunc()
    {
    
    
        Debug.Log("调用单例测试方法!!!");
    }

    public void Update()
    {
    
    
        Debug.Log("单例Update方法!!!");
    }
}
public class Test : MonoBehaviour
{
    
    
    void Start()
    {
    
    
        SingletonSystem.Initialize();
        AssemblyManager.Initialize();

        TestSingleton.Instance.TestFunc();
    }


    private void Update()
    {
    
    
        SingletonSystem.Update();

        if (Input.GetKeyDown(KeyCode.P))
        {
    
    
            TestSingleton.Instance.TestFunc();
        }
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zzzsss123333/article/details/132622235
今日推荐