kotlin版对象复用池

项目中经常用到对象池复用,但是不一样的对象对应的复用池都不统一。想着能否有一个对象池,可以不用关心对象是啥,实现对象池的功能?
对象池的功能需要支持:

  1. 不关系对象是什么,都能复用。
  2. 如何生产对象?
  3. 如何回收对象?

对于问题点 1 可以借助泛型和集合来实现。本来想参考Message来实现,但是没法给对象动态添加一个next属性,因此用一个集合来保存
对于问题点 2,如果我们复用集合里面有,直接返回集合里面的,如果没有,我们要实现化一个对象返回,但是有不知道他是什么类型,首先想到的是传个Class进来,这样我们就可以反射实例化一个对象
对于问题点3,所谓回收对象,就是把对象的属性都赋默默认值,然后把该对象存入集合。对象属性赋默认值也可以反射实现

对于第二点反射实例化一个对象,因为对象可能有多个构造器。而我们又不知道调用者到底要实例化哪一个,因此从所有构造器中选第一个实例化。为了给调用灵活性,这里我们添加一个factory给调用者自己决定是否要实例化一个对象。如果调用者自己创建了,就直接返回
上代码

class AnyPool(private val clazz: Class) {
    companion object{
      //方便调用者生成一个AnyPool对象
       inline fun  getAnyPool():AnyPool{
            return AnyPool(T::class.java)
        }
    }
    //复用池
    private val nodes = mutableListOf()
    //从复用池拿,如果复用池没有,先从factory创建,如果factory没有,则反射生成一个
    fun getFromPool(factory: () -> T? = { null }): T {
        if (nodes.isEmpty()) {
            println("from create")
            return factory() ?: let {
                val constructor = clazz.constructors[0]
                val parameters = constructor.parameters
                val params = arrayOfNulls(parameters.size)
                parameters.forEachIndexed { index, parameter ->
                    params[index] = parameter.type.getDefault()
                }
                constructor.newInstance(*params) as T
            }


        }
        println("form pool")
        return nodes.removeAt(0)
    }
    //回收该对象到复用池
    fun recycle(node:T){
        node.clearField()
        nodes+=node
    }
    private  fun  Class.getDefault():K?{
        return when(this){
             Int::class.java->0 as K
            Boolean::class.java->false as K
            Float::class.java->0f as K
            Double::class.java->0.0 as K
            Long::class.java->0L as K
            Short::class.java->0 as K
            Char::class.java->'0' as K
            Byte::class.java->0 as K
            else -> null
        }
    }
  //将该对象属性赋默认值
    private fun T.clearField(){
        (clazz.declaredFields+clazz.fields).forEach {field->
            field.isAccessible = true
            field.set(this,field.type.getDefault())
        }
    }

}

测试代码

data class Bean (var age:Int,var name:String?,var bean: Bean?)
fun testAnyPool(){
        val anyPool = AnyPool.getAnyPool()
        val list = mutableListOf()
        val test = Bean(11,"222",null)
       for (i in 0..4){
            val  bean = when {
               i%2==0-> anyPool.getFromPool {
                    Bean(i, "我是工厂创建的", test)
                }
                else ->{
                    anyPool.getFromPool()
                }
            }
            bean.age = i
            bean.bean = test
            list+=bean
            println(bean)
        }
        list.forEach {
            anyPool.recycle(it)
        }
        for (i in 1..5){
            println(anyPool.getFromPool())
        }
    }

输出,可以看到很好的满足了对象池的功能

from create
Bean(age=0, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=1, name=null, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=2, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=3, name=null, bean=Bean(age=11, name=222, bean=null))
from create
Bean(age=4, name=我是工厂创建的, bean=Bean(age=11, name=222, bean=null))
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)
form pool
Bean(age=0, name=null, bean=null)

Process finished with exit code 0

你可能感兴趣的:(kotlin版对象复用池)