Skip to main content

简单封装个对象池

看到公司使用 ObjectPool 对象池缓存rabbitmq连接

看了下具体实现,感觉用起来太繁琐

需要实现 IPooledObjectPolicy 接口, 自定义一个 Policy

而这个接口中最主要的可能就是 Create 方法, 即在池中无对象的情况下如何创建新的

所以我觉得可以尝试封装一下,简化使用

第一版

首先定义一个泛型 Policy

MyPoolPolicy

public class MyPoolPolicy<T> : IPooledObjectPolicy<T>
{
public static Func<T> CreateFunc = null;
public static Func<T, bool> ReturnFunc = null;
public T Create()
{
if (CreateFunc == null)
return default;
return CreateFunc();
}
public bool Return(T obj)
{
return ReturnFunc(obj);
}
}

定义两个静态的委托, 修改委托即可改变 Create 中的实现

然后简单写一个静态工具方法用于创建对象池

public class PoolTool
{
public static ObjectPool<T> CreatePool<T>(Func<T> create, Func<T, bool> returnFunc = null) where T : class
{
MyPoolPolicy<T>.CreateFunc = create;
returnFunc ??= item => true;
MyPoolPolicy<T>.ReturnFunc = returnFunc;
return new DefaultObjectPool<T>(new MyPoolPolicy<T>());
}
}

一般来说 Return 不是太重要,可以给个默认的实现

使用的时候就比较简单了

var pool = PoolTool.CreatePool(() => {
// 一些自定义的东西
return new MyClass {
...
}
});

这样就可以获取到一个可用的对象池, 调用 pool.Get() 就可以生成一个 MyClass 对象

第二版

上一版存在一个问题, 由于只有一个静态的委托对象, 所以当我再次调用 PoolTool.CreatePool<MyClass>() 传入新委托时, 之前创建的 pool 实现会被修改为传入的新的委托, 这可能会产生一些问题, 虽然在一般情况下一种类型只会有一种实现, 但是封装的时候也必须要考虑的到这种情况

public class MyPoolPolicy<T> : IPooledObjectPolicy<T>
{
/// <summary>
/// 每个pool实例的index标记,用于从集合中取出对应的委托
/// </summary>
public int? Index { get; set; }
public static Func<int, T> CreateFunc = null;
public static Func<int, T, bool> ReturnFunc = null;
public static List<Func<T>> CreateFuncs = new();
public static List<Func<T, bool>> ReturnFuncs = new();
public MyPoolObjectPolicy() { }
public MyPoolObjectPolicy(int index)
{
Index = index;
}

public T Create()
{
return CreateFunc(Index.Value);
}

public bool Return(T obj)
{
return ReturnFunc(Index.Value, obj);
}
}

public class PoolTool
{
public static ObjectPool<T> CreatePool<T>(Func<T> create, Func<T, bool> returnFunc = null) where T : class
{
MyPoolPolicy<T>.CreateFuncs.Add(create);
returnFunc ??= item => true;
MyPoolPolicy<T>.ReturnFuncs.Add(returnFunc);

var policy = new MyPoolPolicy<T>(MyPoolPolicy<T>.CreateFuncs.Count - 1);

MyPoolPolicy<T>.CreateFunc = (index) => MyPoolPolicy<T>.CreateFuncs[index]();
MyPoolPolicy<T>.ReturnFunc = (index, item) => MyPoolPolicy<T>.ReturnFuncs[index](item);
return new DefaultObjectPool<T>(policy);
}
}

每次传入的委托会放到 CreateFuncs,ReturnFuncs 集合中,

并且每个新建的pool实例都会有一个用于标记的 Index

两者配合即可让同一个 MyPoolPolicy 拥有多个实现

caution

本文只是提供一个简单的思路, 更加复杂的问题需要结合实际情况考虑再做修改