項(xiàng)目中經(jīng)常用到對象池復(fù)用布朦,但是不一樣的對象對應(yīng)的復(fù)用池都不統(tǒng)一腿倚。想著能否有一個(gè)對象池纯出,可以不用關(guān)心對象是啥,實(shí)現(xiàn)對象池的功能敷燎?
對象池的功能需要支持:
- 不關(guān)系對象是什么暂筝,都能復(fù)用。
- 如何生產(chǎn)對象硬贯?
- 如何回收對象焕襟?
對于問題點(diǎn) 1 可以借助泛型和集合來實(shí)現(xiàn)。本來想?yún)⒖糓essage來實(shí)現(xiàn)饭豹,但是沒法給對象動態(tài)添加一個(gè)next屬性鸵赖,因此用一個(gè)集合來保存
對于問題點(diǎn) 2,如果我們復(fù)用集合里面有拄衰,直接返回集合里面的它褪,如果沒有,我們要實(shí)現(xiàn)化一個(gè)對象返回翘悉,但是有不知道他是什么類型茫打,首先想到的是傳個(gè)Class進(jìn)來,這樣我們就可以反射實(shí)例化一個(gè)對象
對于問題點(diǎn)3,所謂回收對象老赤,就是把對象的屬性都賦默默認(rèn)值轮洋,然后把該對象存入集合。對象屬性賦默認(rèn)值也可以反射實(shí)現(xiàn)
對于第二點(diǎn)反射實(shí)例化一個(gè)對象抬旺,因?yàn)閷ο罂赡苡卸鄠€(gè)構(gòu)造器弊予。而我們又不知道調(diào)用者到底要實(shí)例化哪一個(gè),因此從所有構(gòu)造器中選第一個(gè)實(shí)例化开财。為了給調(diào)用靈活性块促,這里我們添加一個(gè)factory給調(diào)用者自己決定是否要實(shí)例化一個(gè)對象。如果調(diào)用者自己創(chuàng)建了床未,就直接返回
上代碼
class AnyPool<T>(private val clazz: Class<T>) {
companion object{
//方便調(diào)用者生成一個(gè)AnyPool對象
inline fun <reified T> getAnyPool():AnyPool<T>{
return AnyPool(T::class.java)
}
}
//復(fù)用池
private val nodes = mutableListOf<T>()
//從復(fù)用池拿竭翠,如果復(fù)用池沒有,先從factory創(chuàng)建薇搁,如果factory沒有斋扰,則反射生成一個(gè)
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)
}
//回收該對象到復(fù)用池
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
}
}
//將該對象屬性賦默認(rèn)值
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, "我是工廠創(chuàng)建的", 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=我是工廠創(chuàng)建的, 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=我是工廠創(chuàng)建的, 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=我是工廠創(chuàng)建的, 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