GameFramework摘录 - 1. ReferencePool

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

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

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

public static class ReferencePool
{
    private sealed class ReferenceCollection
    {
        private readonly Queue 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();
            m_ReferenceType = referenceType;
        }

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

        public T Acquire() 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 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 s_ReferenceCollections = new Dictionary();

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

            s_ReferenceCollections.Clear();
        }
    }

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

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

    private static ReferenceCollection GetReferenceCollection() 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()ReferencePool.Release()

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

你可能感兴趣的:(GameFramework摘录 - 1. ReferencePool)