复杂嵌套的对象池(1)——先进先出的队列结构

【基础知识】

如果不知道什么是对象池,请先了解下。

关于对象池,我们需要知道池子里的最大容量和当前可用的对象数量;需要从对象池里获取和回收对象;随着生成的对象越来越多,池子会扩容,要有扩容的操作和策略,反之要有缩容的操作和策略。我们可以根据这些来定义简单的接口和相关枚举:

using System.Collections;
using System.Collections.Generic;
using System;


namespace Cache
{
    public interface ICountable
    {
        //数量和容量
        int Count();
        int Capacity();
    }

    public interface IShrinkable
    {
        bool Shrink(ShrinkStrategy shrinkStrategy, float percent,int count, bool weedout);//WeedOut是指缩容时是否强行淘汰对象
    }

    public interface ICache<T>:ICountable,IShrinkable,IDisposable
    {
        //获取和放入,一一对应
        bool Get(out T value);
        bool Put(T value);

        //扩容和缩容,一一对应,自动扩容,手动缩容
        bool Expansion();      
    }

    public enum ExpansionStrategy 
    { 
        NONE = 0,//不扩容
        FIXEDCOUNT,//固定数量
        DOUBLE,//双倍
        PERCENT,//一定比例
    }

    public delegate void WeedOutDelegate<T> (T value);

    public enum ShrinkStrategy
    {
        NONE = 0,
        FIXEDCOUNT,
        DOUBLE,
        PERCENT,
    }
}

可以看到没有定义一个大而全的接口,反而是定义了很多小的接口 ,这是因为大而全的接口可以拆分为ABC等部分,而另外的某个功能也会用到这些部分。 

实现和注释请看代码

【代码实现】

using System;
using System.Collections;
using System.Collections.Generic;

namespace Cache
{
    public class FIFO<T> : ICache<T>
    {
        private Queue<T> queue;//直接用队列,也可以自己用链表实现
        private int capacity;

        private ExpansionStrategy expansionStrategy;
        private WeedOutDelegate<T> weedOutDelegate;

        private bool disposed;

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="capacity"></param>
        /// <param name="expansionStrategy">默认没有扩容</param>
        /// <param name="weedOutDelegate"></param>
        public FIFO(int capacity, ExpansionStrategy expansionStrategy = ExpansionStrategy.NONE, WeedOutDelegate<T> weedOutDelegate = null)
        {          
            this.capacity = capacity;
            this.weedOutDelegate = weedOutDelegate;
            this.expansionStrategy = expansionStrategy;

            queue = new Queue<T>(capacity);
        }

        public int Capacity()
        {
            return capacity;
        }

        public int Count()
        {
            return queue.Count;
        }

        public bool Get(out T value)
        {
            return queue.TryDequeue(out value);
        }

        public bool Put(T value)
        {
            if (!value.GetType().IsValueType && default(T) == null)//如果是引用类型,且为空,要返回false,因为这些操作的返回类型不能是void,而要是bool
            {
                return false;
            }
            if (queue.Count == capacity)//如果当前的数量等于容量,那么要先扩容
            {
                if (!Expansion())
                {
                    if(weedOutDelegate != null)
                    {
                        weedOutDelegate(value);//如果扩容失败,将这个对象淘汰
                    }
                    else//否则Put 失败
                    {
                        return false;
                    }
                }
                    
            }
            queue.Enqueue(value);
            return true;
        }

        public bool Expansion()
        {
            bool result = true;
            switch(expansionStrategy)
            {
                case ExpansionStrategy.NONE: result = false;break;
                case ExpansionStrategy.FIXEDCOUNT: ExpansionWithFixedCount(3);break;//可以把参数放到构造器中,这里省略不写了
                case ExpansionStrategy.DOUBLE:capacity *= 2;break;
                case ExpansionStrategy.PERCENT: ExpansionWithPercent(0.3f);break;
            }
            return result;
        }

        private void ExpansionWithFixedCount(int count)
        {
            if (count < 0)
                count = 0;

            capacity += count; //使用的默认队列结构,会自动扩容,只要增加容量即可
        }

        private void ExpansionWithPercent(float value)
        {
            value = Math.Clamp(value, 0f, 1f);
            capacity = (int)(capacity * (1 + value ));
        }

        //扩容自动,缩容由外部调用
        public bool Shrink(ShrinkStrategy shrinkStrategy,float percent = 0, int count = 0,bool weedout = false)
        {
           bool result = true;
           switch(shrinkStrategy)
           {
                case ShrinkStrategy.NONE:break;
                case ShrinkStrategy.FIXEDCOUNT:
                    {
                        int residualCapacity = capacity - count;
                        if (residualCapacity < 0)//容量不能小于0
                        {
                            result = false;
                            break;
                        }
                        if (residualCapacity >= queue.Count)
                        {
                            capacity = residualCapacity;
                        }
                        else
                        {
                            if (weedout)//淘汰
                            {
                                int num = queue.Count - residualCapacity;
                                while (num > 0)
                                {
                                    result = WeedOut();
                                    num--;
                                }
                                capacity = residualCapacity;
                            }
                            else
                            {
                                capacity = queue.Count;
                            }
                        }
                        break;
                    }
                case ShrinkStrategy.DOUBLE:
                    count = capacity / 2;
                    Shrink(ShrinkStrategy.FIXEDCOUNT,percent, count, weedout);
                    break;
                case ShrinkStrategy.PERCENT:
                    count = (int)(capacity * percent);
                    Shrink(ShrinkStrategy.FIXEDCOUNT, percent, count, weedout);
                    break ;
            }
            return result;
        }

        private bool WeedOut()
        {
            if (queue.Count == 0)//做个保护,虽然不会出现这种情况
                return false;

            T value = queue.Dequeue();
            weedOutDelegate?.Invoke(value);
            return true;

        }

        ~FIFO()
        {
            this.Dispose(false);
        }
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(true);
        }

        protected virtual void Dispose(bool dispose)
        {
            if(disposed)
            {
                return;
            }

            if(dispose)
            {
                //这个不用处理非托管资源,用委托传递出去
            }

            foreach (var item in queue)
            {
                weedOutDelegate?.Invoke(item);
            }
            queue.Clear();
            disposed = true;
        }

    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值