对象池的定义
对象池模式是单例模式的一个变种,它提供了获取一系列相同对象实例的入口。当你需要对象来代表一组可替代资源的时候就变的很有用,每个对象每次可以被一个组件使用。
在我看来,对象池是用于解决某一常用对象不断创建销毁时造成的大量资源损耗问题。
用筷子举例,如果每次吃饭都需要竹制的筷子,那么每次吃饭之前,你都需要去制作竹筷子;让我们简单一点,制作一些筷子,和一个筷子笼,筷子吃完就洗一下,放到筷子笼,下次吃饭再拿出来。很明显这样方便很多。
那么,把筷子笼,以及清洗筷子以及针对筷子的存取行为,合起来,就是对象池。
实际使用
对象池中,都是已经被创建的对象,它们当前未被实际使用,当要用到时,从池中取出一个,注意是取出,也就是池子中就会少一个;如果池子中是空的,那么就只能创建一个新的出来了。
对象池一般都会定义最大对象数量,对象用完之后,不会被直接销毁,将会被存进池子里面,如果发现池子已经满了,那么就会直接销毁,其实很好理解
代码
贴上相关代码,因为对象池都是使用数组,所以一共有三份代码,分别是对象池的管理,数组的创建,排序相关的代码
对象池的管理
--[[
对象池的管理
--]]
ObjPool = ObjPool or BaseClass()
local ObjPool = ObjPool
function ObjPool:__init(max_create)
self.create_count = 0
self.max_create = max_create
self.free_list = Array.New()
end
function ObjPool:__delete()
local count = self.free_list:GetSize()
for index = 1, count do
local obj = self.free_list:PopBack()
obj:DeleteMe()
end
self.create_count = 0
self.free_list = nil
end
function ObjPool:GetObjFreeList()
local count = self.free_list:GetSize()
local obj = nil
if count > 0 then
obj = self.free_list:PopBack()
obj:ResetObj()
else
self.create_count = self.create_count + 1
end
return obj
end
function ObjPool:ReleaseObj(obj)
local count = self.free_list:GetSize()
local diff_count = 2 * count - self.create_count
if diff_count < self.max_create then
obj:ReleaseObj()
self.free_list:PushBack(obj)
else
obj:DeleteMe()
obj = nil
self.create_count = self.create_count - 1
end
end
function ObjPool:GetObjCount()
return self.free_list:GetSize()
end
function ObjPool:ReleaseAll()
local count = self.free_list:GetSize()
for index = 1, count do
local obj = self.free_list:PopBack()
obj:DeleteMe()
end
self.create_count = 0
end
数组的管理
--[[
数组的管理
--]]
--[[
数组索引由下标0到下标n-1
--]]
Array = Array or BaseClass()
local Array = Array
local table = table
local table_insert = table.insert
local table_remove = table.remove
Array.UPPER = 1 --升序
Array.LOWER = 2 --降序
function Array:__init()
self.size = 0
self.items = {}
end
function Array:IsEmpty()
return self.size <= 0
end
--[[
在数组尾部插入一项
@para1 val in 插入数组的项
--]]
function Array:PushBack( val )
self.size = self.size + 1
self.items[self.size] = val
end
--[[
从数组尾部移除一项并返回
@return 返回移除的项
--]]
function Array:PopBack()
if self.size > 0 then
local val =self.items[self.size]
self.items[self.size] = nil
self.size = self.size - 1
return val
end
return nil
end
--[[
从数组头部添加一项
@para1 val in 一个数组项
--]]
function Array:PushFront( val )
table_insert(self.items, 1, val)
self.size = self.size + 1
end
--[[
从数组头部移除一项并返回
@return 返回移除的项
--]]
function Array:PopFront()
if self.size > 0 then
local val = self.items[1]
table_remove(self.items, 1)
self.size = self.size - 1
return val
end
return nil
end
--[[
逐项对数组每一项执行某操作
@para1 func in 每项执行的函数,类型为 func(item)
--]]
function Array:ForEach(func)
for i = 1, self.size do
func(self.items[i])
end
end
--[[
按索引获取数组中的某项
@para1 index in 数组索引
@return 返回对应索引的项的项
--]]
function Array:Get(index)
if index < self.size then
return self.items[index + 1]
else
print("Array:Get() out of index! " .. tostring(index))
end
end
function Array:Contains(val)
for i = 1, self.size do
local item = self.items[i]
if item == val then
return true
end
end
return false
end
function Array:IndexOf(val)
for i = 1, self.size do
local item = self.items[i]
if item == val then
return i
end
end
return -1
end
function Array:GetList()
return self.items
end
--[[
按索引设置数组中的某项
@para1 index in 数组索引
@para2 val in 设置的值
--]]
function Array:Set(index, val)
if index < self.size then
self.items[index + 1] = val
else
print("Array:Set() out of index!")
end
end
--[[
逐项对数组每一项执行某操作
@return 数组大小
--]]
function Array:GetSize()
return self.size
end
--[[
对数组执行升序排序操作
@para1 key_name in 用来排序的数组项Key(可选参数)
--]]
function Array:LowerSort(key_name)
local sort_func
if key_name then
sort_func = SortTools.KeyLowerSorter(key_name)
else
sort_func = SortTools.ItemLowerSorter()
end
table.sort(self.items, sort_func)
end
--[[
对数组执行降序排序操作
@para1 key_name in 用来排序的数组项Key(可选参数)
--]]
function Array:UpperSort(key_name)
local sort_func
if key_name then
sort_func = SortTools.KeyUpperSorter(key_name)
else
sort_func = SortTools.ItemUpperSorter()
end
table.sort(self.items, sort_func)
end
--[[
依据项中的Key查找数组中的一项
@para1 item_key in 用来搜索的数组项Key
@para2 val in 要查找的item_key的值
@para3 offset in 开始检索的位置
@return 返回检索到的项,检索到的项的Index
--]]
function Array:FindByKey(item_key, val, offset)
offset = offset or 0
for i = offset + 1, self.size do
local item = self.items[i]
if item[item_key] == val then
return item, i-1
end
end
return nil, -1
end
--[[
依据项中的Key查找数组中的一项
@para1 equal_func in 用来检测数组项是否符合要求的函数
@para2 offset in 开始检索的位置
@return 返回检索到的项,检索到的项的Index
--]]
function Array:FindByFunc(equal_func, offset)
offset = offset or 0
for i = offset + 1, self.size do
local item = self.items[i]
if equal_func(item) then
return item, i-1
end
end
return nil, -1
end
--[[
移除对应索引的项
@para1 index in 待删除的索引
--]]
function Array:Erase(index)
index = index or self.size - 1
if index >= 0 and index < self.size then
table_remove(self.items, index + 1)
self.size = self.size -1
end
end
--[[
在对应位置插入一项
@para1 key_name in 用来排序的数组项Key(可选参数)
--]]
function Array:Insert(item, index)
index = index or 0
table_insert(self.items, index + 1)
self.size = self.size + 1
end
--[[
返回开始位置到结束位置之间的数组列表
@para1 begin_pos 开始位置
@para2 end_pos 结束位置
@return array
--]]
function Array:GetSubArray(begin_pos,end_pos)
local ret = Array.New()
local index = 0
local len = self:GetSize()
for i=begin_pos,end_pos-1 do
if i >= len then
break
end
ret:PushBack(self:Get(i))
end
return ret
end
--[[
返回数组中满足函数equal_func的子列表
@para1 equal_func 用来检测数组项是否符合要求的函数
@return array
--]]
function Array:Filter(equal_func)
local ret = Array.New()
for i = 1, self.size do
local item = self.items[i]
if equal_func(item) then
ret:PushBack(item)
end
end
return ret
end
--[[
二分查找方式插入一项, 用于快速构建一个排序数组
@para1 item in 插入到数组中的项
@para2 comp_func in 比较函数
--]]
--[[
function Array:BinaryInsert(item, comp_func)
SortTools.BinaryInsert(self.items, item, comp_func)
end
--]]
function Array.GetArray(array,begin_pos,end_pos)
if array == nil then
return {}
end
local ret = {}
for i=begin_pos,end_pos do
if i > #(array) then
break
end
table_insert(ret,array[i])
end
return ret
end
function Array.GetArrayByScale(array,scale,length)
if array == nil then
return {}
end
local ret = {}
local begin_pos = math.floor(#(array)*scale) + 1
local end_pos = begin_pos+length-1
return Array.GetArray(array,begin_pos,end_pos)
end
--[[
对数组执行排序操作
@param arg 需要比较的表项中的多个key,
跟key对应的排序方式(升序:Array.UPPER还是降序:Array.LOWER)
@传参格式:arg = {{key1,key2,...},{Array.UPPER,Array.LOWER,...}}
不填写排序方式默认为升序Array.UPPER
--]]
function Array:sortOn( ... )
local arg = {...}
local sort_func = nil
if arg == nil or arg[1] == nil then
self:UpperSort()
return
elseif type(arg[1]) ~= "table" or #(arg[1]) <= 1 then
if arg[2] == nil or arg[2] == Array.UPPER then
self:UpperSort(arg[1])
else
self:LowerSort(arg[1])
end
return
end
SortTools.MoreKeysSorter(self.items, arg[1],arg[2])
end
排序代码
SortTools = {}
--[[
排序代码
--]]
--[[
从小到大排序的算子(用于表项)
@para2 sort_key_name 需要比较的表项中的key
--]]
function SortTools.KeyLowerSorter(sort_key_name)
return function(a, b)
if a[sort_key_name] < b[sort_key_name] then
return true
else
return false
end
end
end
--[[
从大到小排序的算子(用于表项)
@para2 sort_key_name 需要比较的表项中的key
--]]
function SortTools.KeyUpperSorter(sort_key_name)
return function(a, b)
if a[sort_key_name] > b[sort_key_name] then
return true
else
return false
end
end
end
--[[
多条件排序支持混排
@param tbl 要排序的table
@param arg 需要比较的表项中的多个key,
跟key对应的排序方式(升序:Array.UPPER还是降序:Array.LOWER)
@传参格式:arg = {{key1,key2,...},{Array.UPPER,Array.LOWER,...}}
不填写排序方式默认为升序Array.UPPER
@create 12/18/2013
--]]
function SortTools.MoreKeysSorter(tbl, ...)
local arg = {...}
local func = nil
--参数为空的时候直接对表项排序--
if arg == nil or #arg == 0 then
func = SortTools.ItemUpperSorter()
end
local argName = arg[1]
local argType = arg[2]
local sort_func = nil
if argName == nil then
func = SortTools.ItemUpperSorter()
--参数为单个的时候调用单个排序函数--
elseif type(argName) ~= "table" or #argName <= 1 then
if argType == nil or argType == Array.UPPER then
func = SortTools.KeyUpperSorter(argName)
else
func = SortTools.KeyLowerSorter(argName)
end
end
--多参数排序方法--
func = function(a, b)
local len = #argName
local i = 1
while len > 0 do
if argType == nil or argType[i] == nil or argType[i] == Array.UPPER then
if a[argName[i]] > b[argName[i]] then
return true
elseif a[argName[i]] ~= b[argName[i]] then
return false
end
else
assert(argName[i] and a[argName[i]] and b[argName[i]], "sort tools error i:"..i)
if a[argName[i]] < b[argName[i]] then
return true
elseif a[argName[i]] ~= b[argName[i]] then
return false
end
end
len = len - 1
i = i + 1
end
return false
end
table.sort(tbl, func)
end
--[[
从小到大排序的算子(用于普通项)
--]]
function SortTools.ItemLowerSorter()
return function(a, b)
return a < b
end
end
--[[
从大到小排序的算子(用于普通项)
--]]
function SortTools.ItemUpperSorter()
return function(a, b)
return a > b
end
end
function SortTools.BinaryInsert(t, value, fcomp)
-- Initialise compare function
fcomp = fcomp or SortTools.ItemLowerSorter
-- Initialise numbers
local istart, iend, imid, istate = 1, #t, 1, 0
-- Get insert position
while istart <= iend do
-- calculate middle
imid = math.floor( (istart+iend)/2 )
-- compare
if fcomp( value, t[imid] ) then
iend, istate = imid - 1, 0
else
istart, istate = imid + 1, 1
end
end
table.insert(t, (imid + istate), value)
return (imid + istate)
end
function SortTools.BinarySearch(t, value, equal_func, compare_func)
-- Initialise numbers
local max_t = #t
local istart, iend, imid = 1, max_t, 0
--[[
if istart == iend then
local find_t = nil
if equal_func(t[istart], value) then
find_t = {istart, iend}
end
return find_t
end
]]
-- Binary Search
while istart <= iend do
-- calculate middle
imid = math.floor( (istart+iend)/2 )
-- get compare value
local value2 = t[imid]
-- get all values that match
if equal_func(value, value2) then
local tfound,num = { imid,imid },imid - 1
while (num >= 1) and (equal_func(value, t[num])) do
tfound[1],num = num,num - 1
end
num = imid + 1
while (num <= max_t) and (equal_func(value, t[num])) do
tfound[2],num = num,num + 1
end
return tfound
-- keep searching
elseif compare_func(value, value2) then
iend = imid - 1
else
istart = imid + 1
end
end
end
--冒泡排序
--list:待排序列表
--sort_word:排序元素
--descending:默认 降序,false 升序
function SortTools.BubbleSort(list,sort_word,descending)
local comp = function(item0,item1)
--将空项排在后面
if item0[sort_word] == nil and item0[sort_word] ~= nil then
return true
end
if item0[sort_word] ~= nil and item1[sort_word] ~= nil then
if descending == false then
--升序
if item0[sort_word] > item1[sort_word] then
return true
end
else
--降序
if item0[sort_word] < item1[sort_word] then
return true
end
end
end
return false
end
local length = #(list)
local result = false
local temp = nil
local flag = true
for i=1,length - 1 do
if not flag then
break
end
flag = false
for k=1,length - i do
result = comp(list[k],list[k+1])
if result then
flag = true
temp = list[k]
list[k] = list[k+1]
list[k+1] = temp
end
end
end
end
--根据func进行冒泡
--返回true,则将后一个替换前一个
--返回false,则不作处理
function SortTools.SortListByFunc(list, func)
local length = #(list)
local result = false
local temp = nil
local flag = true
for i=1,length - 1 do
if not flag then
break
end
flag = false
for k=1,length - i do
result = func(list[k],list[k+1])
if result then
flag = true
temp = list[k]
list[k] = list[k+1]
list[k+1] = temp
end
end
end
end
使用示例
function Scene:CreateSprite(owner)
--查看当前是否已存在残余数据
local sprite = self.sprite_list[owner.id]
if sprite ~= nil then
--已存在残余数据,存入池子中
self.sprite_pool:ReleaseObj(sprite)
self.sprite_list[owner.id] = nil
end
--从对象池取出
sprite = self.sprite_pool:GetObjFreeList()
if sprite == nil then
--池子空的,自己创建一个
sprite = Sprite.New()
end
self.sprite_list[owner.id] = sprite
return sprite, true
end
function Scene:DeleteSprite(instance_id )
local sprite = self.sprite_list[instance_id]
if sprite ~= nil then
--通过唯一id找到对象存入池子中
self.sprite_list[instance_id] = nil
self.sprite_pool:ReleaseObj(sprite)
end
end