首页 > 其他 > 详细

GameFramework摘录 - 1. ReferencePool

时间:2019-12-10 21:26:54      阅读:115      评论:0      收藏:0      [点我收藏+]

GameFramework是一个结构很优秀的Unity游戏框架,但意图似乎在构建可跨引擎的框架?对要求不高的小型个人(不专业)开发来说有些设计过度了,但其中的设计精华很值得学习。
首先来说一下其中的ReferencePool “引用池”,实质是一组自动管理(不需要单独手动创建销毁)的对象池。
抽取核心代码,并根据个人习惯修改一些命名后,代码如下

public interface IReference
{
    // 采用此类进行清理,清理后应当和刚执行new()后创建得到的新对象状态相同
    void Clean();
}

IReference 是自定义的一个接口,将需要进行池化存储的类继承此接口,就可以通过引用池来存取

public static class ReferencePool
{
    private sealed class ReferenceCollection
    {
        private readonly Queue<IReference> m_Objects;
        private readonly Type m_ReferenceType;
        public Type ReferenceType { get { return m_ReferenceType; } }
        public int UnusedReferenceCount { get { return m_Objects.Count; } }
        public int UsingReferenceCount { get; private set; }

        public ReferenceCollection(Type referenceType)
        {
            m_Objects = new Queue<IReference>();
            m_ReferenceType = referenceType;
        }

        public void Clear()
        {
            lock (m_Objects)
            {
                m_Objects.Clear();
            }
        }

        public T Acquire<T>() where T : class, IReference, new()
        {
            if (typeof(T) != m_ReferenceType)
            {
                throw new Exception("Wrong Type");
            }

            UsingReferenceCount++;
            lock (m_Objects)
            {
                if (m_Objects.Count > 0)
                {
                    return m_Objects.Dequeue() as T;
                }
            }

            return new T();
        }

        public void Release<T>(T obj) where T : class, IReference, new()
        {
            if (typeof(T) != m_ReferenceType)
            {
                throw new Exception("Wrong Type");
            }

            obj.Clean();

            lock (m_Objects)
            {
                if (m_Objects.Contains(obj))
                {
                    throw new Exception("The reference has been released.");
                }
                
                m_Objects.Enqueue(obj);
            }

            UsingReferenceCount--;
        }
    }
}

ReferenceCollection是被管理的对象集合(将单词“Reference”替换为“Object”更好理解),即一个通常意义的对象池,提供了获取、释放对象的接口。原代码中一些用于统计、调试的属性被移除(实际在这里UnusedReferenceCount和UsingReferenceCount也可以先移除)

public static class ReferencePool
{
    private static readonly Dictionary<Type, ReferenceCollection> s_ReferenceCollections = new Dictionary<Type, ReferenceCollection>();

    public static void Clear()
    {
        lock (s_ReferenceCollections)
        {
            foreach (var pair in s_ReferenceCollections)
            {
                pair.Value.Clear();
            }

            s_ReferenceCollections.Clear();
        }
    }

    public static T Acquire<T>() where T : class, IReference, new()
    {
        return GetReferenceCollection<T>().Acquire<T>();
    }

    public static void Release<T>(T obj) where T : class, IReference, new()
    {
        GetReferenceCollection<T>().Release<T>(obj);
    }

    private static ReferenceCollection GetReferenceCollection<T>() where T : class, IReference, new()
    {
        ReferenceCollection referenceCollection = null;
        Type type = typeof(T);
        lock (s_ReferenceCollections)
        {
            if (!s_ReferenceCollections.TryGetValue(type, out referenceCollection))
            {
                referenceCollection = new ReferenceCollection(type);
                s_ReferenceCollections.Add(type, referenceCollection);
            }
        }

        return referenceCollection;
    }
}

ReferencePool最终提供了统一的对外接口ReferencePool.Acquire<T>()ReferencePool.Release<T>()

在此基础上,可以添加原代码中的添加、删除、获取、释放计数
或设置ReferenceCollection的数量上限,如一个基于GameFramework的框架 HTFramework

GameFramework摘录 - 1. ReferencePool

原文:https://www.cnblogs.com/lunoctis/p/12018652.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!