面试——谈谈对象池模式(个人总结)

本文来自对 https://gpp.tkchu.me/object-pool.html 学习后自己的总结

概念

对象池,及对象的容器,本身是一个对象,内部管理一个包含数个可复用对象的容器。可以方便的取出和回收。池在初始化时就创建整个对象集合(通常为一次连续分配)。在需要时取出,使用结束后回收,轻易地重用对象而不必每次创建销毁时消耗内存和性能。

解决

在Unity中,我们使用对象池主要解决两个问题:

1.减少new的时候,寻址造成的损耗,消耗的原因主要是内存碎片;

2.减少 Object.Instantiate 时内部进行序列化和反序列化的CPU损耗。

应用场景

对象是需要频繁创建和销毁的。

大小相仿。

内存分配缓慢或会导致内存碎片(频繁销毁导致内存中的不连贯)。

封装了数据库和网络连接这样昂贵又可以重用的资源

细节与应对

可能在不需要的资源上浪费资源。要保证池内存适量,太小太大不可取

取用时池中已空。意味着同时只能激活固定数量的对象,在某种程度上这是好事。 不会使先使用对象使用过多内存而造成后面重要对象无内存可用,但我们依然要想办法解决:

1.完全阻止。对于重要的对象,我们增加相应池的大小,无论获取多少,都不溢出。

2.不要再创建,在已有对象已经很引人注目的情况下(满屏的粒子效果),我们可以不出现新的对象

3.强制干掉一个已有对象。如果已有对象的消失要比新对象的出现更不引人察觉

4.增加池的大小。在运行状态下动态增加池的大小,但要考虑增加内存不在需要时是否缩小池

每个对象的大小是否固定。如果是,很好,但是如果要储存不同类型的对象或者子类实例,就需要保证每个位置可以储存下最大对象,这可能造成内存浪费。如果大小差异很大,建议再细分池

设计

首先,定义分配(Allocate)和回收(Recycle)接口

public interface IPool<T>
{
     T Allocate();
     bool Recycle(T obj);
}

(使用泛型可以更加灵活,更容易重用代码)

接下来,对象池的⼀个重要功能就是缓存,要想实现缓存就要求对象可以在对象池内部进⾏创建。

为了更灵活的创建对象,抽象出一个工厂

public interface IObjectFactory<T>
{
     T Create();
}

同时需要计数和数量控制, 以下是全部代码

using System.Collections.Generic;
public abstract class Pool<T> : IPool<T>
{
#region ICountObserverable
     /// <summary>
     /// Gets the current count.
     /// </summary>
     /// <value>The current count.</value>
     public int CurCount
     {
         get { return mCacheStack.Count; }
     }
#endregion
 
     protected IObjectFactory<T> mFactory;
     protected Stack<T> mCacheStack = new Stack<T>();
     /// <summary>
     /// default is 5
     /// </summary>
     protected int mMaxCount = 5;
     
     public virtual T Allocate()
     {
         return mCacheStack.Count == 0
                ? mFactory.Create()
                : mCacheStack.Pop();
     }
     
     public abstract bool Recycle(T obj);
 }

决策

我习惯使用泛型,使对象与对象池解耦。这样可以有通用重用的对象池类

习惯以工厂类的方式初始化对象

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值