对象池适用于:
- 对象的创建很耗时
- 对象频繁地释放再创建
对象池的实现:将释放的对象放进对象池中,在新建对象时,从对象池取对象
public class ObjectPool<T> where T : class, new() { private Stack<T> m_objectStack = new Stack<T>(); public T New() { return (m_objectStack.Count == 0) ? new T() : m_objectStack.Pop(); } public void Store(T t) { m_objectStack.Push(t); } }
改进第一步:对象被重新使用前,reset所有的成员变量。
public class ObjectPool<T> where T : class, new() { private Stack<T> m_objectStack; private Action<T> m_resetAction; //indicate whether need reset private Action<T> m_onetimeInitAction; //indicate whether need initialize public ObjectPool(int initialBufferSize, Action<T> ResetAction = null, Action<T> OnetimeInitAction = null) { m_objectStack = new Stack<T>(initialBufferSize); m_resetAction = ResetAction; m_onetimeInitAction = OnetimeInitAction; } public T New() { if (m_objectStack.Count > 0) { T t = m_objectStack.Pop(); if (m_resetAction != null) m_resetAction(t); return t; } else { T t = new T(); if (m_onetimeInitAction != null) m_onetimeInitAction(t); return t; } } public void Store(T obj) { m_objectStack.Push(obj); } }
参数T被指明为”where T:class,new()”,意味着有两个限制。首先,T必须为一个类(毕竟,只有引用类型需要被obejct-pool);其次,它必须要有一个无参构造函数。
以下是池的使用方法:
class SomeClass : MonoBehaviour { private ObjectPool<List<Vector3>> m_poolOfListOfVector3 = //32为假设的最大数量 new ObjectPool<List<Vector3>>(32, (list) => { list.Clear(); }, (list) => { //初始化容量为1024 list.Capacity = 1024; }); void Update() { List<Vector3> listVector3 = m_poolOfListOfVector3.New(); // do stuff m_poolOfListOfVector3.Store(listVector3); } }
改进第二步:允许一次性回收所有已经池化的对象
public class ObjectPoolWithCollectiveReset<T> where T : class, new() { private List<T> m_objectList; //Stack<T>被List<T>代替,可以跟踪最近创建或释放的对象在list中索引 private int m_nextAvailableIndex = 0; private Action<T> m_resetAction; private Action<T> m_onetimeInitAction; public ObjectPoolWithCollectiveReset(int initialBufferSize, Action<T> ResetAction = null, Action<T> OnetimeInitAction = null) { m_objectList = new List<T>(initialBufferSize); m_resetAction = ResetAction; m_onetimeInitAction = OnetimeInitAction; } public T New() { if (m_nextAvailableIndex < m_objectList.Count) { // an allocated object is already available; just reset it T t = m_objectList[m_nextAvailableIndex]; m_nextAvailableIndex++; if (m_resetAction != null) m_resetAction(t); return t; } else { // no allocated object is available T t = new T(); m_objectList.Add(t); m_nextAvailableIndex++; if (m_onetimeInitAction != null) m_onetimeInitAction(t); return t; } } public void ResetAll() //原本的store() { //重置索引 m_nextAvailableIndex = 0; } }
局限:显然,当我们需要一个其它类型的对象池时就需要重新申明一个。或许我们可以实现一个对用户透明。创建管理所有类型池的ObjectPool。