项目中经常用到对象池复用,但是不一样的对象对应的复用池都不统一。想着能否有一个对象池,可以不用关心对象是啥,实现对象池的功能?
对象池的功能需要支持:
- 不关系对象是什么,都能复用。
- 如何生产对象?
- 如何回收对象?
对于问题点 1 可以借助泛型和集合来实现。本来想参考Message来实现,但是没法给对象动态添加一个next属性,因此用一个集合来保存
对于问题点 2,如果我们复用集合里面有,直接返回集合里面的,如果没有,我们要实现化一个对象返回,但是有不知道他是什么类型,首先想到的是传个Class进来,这样我们就可以反射实例化一个对象
对于问题点3,所谓回收对象,就是把对象的属性都赋默默认值,然后把该对象存入集合。对象属性赋默认值也可以反射实现
对于第二点反射实例化一个对象,因为对象可能有多个构造器。而我们又不知道调用者到底要实例化哪一个,因此从所有构造器中选第一个实例化。为了给调用灵活性,这里我们添加一个factory给调用者自己决定是否要实例化一个对象。如果调用者自己创建了,就直接返回
上代码
class AnyPool<T>(private val clazz: Class<T>) {
companion object{
//方便调用者生成一个AnyPool对象
inline fun <reified T> getAnyPool():AnyPool<T>{
return AnyPool(T::class.java)
}
}
//复用池
private val nodes = mutableListOf<T>()
//从复用池拿,如果复用池没有,先从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<Any?>(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 <K> Class<K>.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<Bean>()
val list = mutableListOf<Bean>()
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
网友评论