对象池设计的详解以及实现

对象池的定义

对象池模式是单例模式的一个变种,它提供了获取一系列相同对象实例的入口。当你需要对象来代表一组可替代资源的时候就变的很有用,每个对象每次可以被一个组件使用。

在我看来,对象池是用于解决某一常用对象不断创建销毁时造成的大量资源损耗问题。
用筷子举例,如果每次吃饭都需要竹制的筷子,那么每次吃饭之前,你都需要去制作竹筷子;让我们简单一点,制作一些筷子,和一个筷子笼,筷子吃完就洗一下,放到筷子笼,下次吃饭再拿出来。很明显这样方便很多。
那么,把筷子笼,以及清洗筷子以及针对筷子的存取行为,合起来,就是对象池。

实际使用

对象池中,都是已经被创建的对象,它们当前未被实际使用,当要用到时,从池中取出一个,注意是取出,也就是池子中就会少一个;如果池子中是空的,那么就只能创建一个新的出来了。
对象池一般都会定义最大对象数量,对象用完之后,不会被直接销毁,将会被存进池子里面,如果发现池子已经满了,那么就会直接销毁,其实很好理解

代码

贴上相关代码,因为对象池都是使用数组,所以一共有三份代码,分别是对象池的管理,数组的创建,排序相关的代码

对象池的管理

--[[
对象池的管理
--]]
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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值