SingletonSystem 单例管理系统

27 篇文章 0 订阅

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();
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值