为了降低模块间的耦合, 很多系统使用事件派发机制, 接收方无需知道派发者是谁.在Qt中,这个系统被称作Slot&Signal, 需要配合moc代码生成机制, 但是系统本身是线程安全的.
这里我们讨论的是lua的事件派发机制, 我将此写成lua模块, 方便配合cocos2dx进行逻辑处理
local Global = _G
local package = _G.package
local setmetatable = _G.setmetatable
local assert = _G.assert
local table = _G.table
local pairs = _G.pairs
local ipairs = _G.ipairs
module "Core.EventDispatcher"
--[[
数据层次
["EventName1"] =
{
["_StaticFunc"] = { Func1, Func2 },
[Object1] = { Func1, Func2 },
[Object2] = { Func1, Func2 },
},
["EventName2"] =
{
...
}
]]
-- 默认调用函数
local function PreInvoke( EventName, Func, Object, UserData, ... )
if Object then
Func( Object, EventName, ... )
else
Func( EventName, ... )
end
end
function New( )
local NewObj = setmetatable( {}, { __index = package.loaded["Core.EventDispatcher"] } )
-- 对象成员初始化
NewObj.mPreInvokeFunc = PreInvoke
NewObj.mEventTable = {}
return NewObj
end
-- 添加
function Add( Self, EventName, Func, Object, UserData )
assert( Func )
Self.mEventTable[ EventName ] = Self.mEventTable[ EventName ] or {}
local Event = Self.mEventTable[ EventName ]
if not Object then
Object = "_StaticFunc"
end
Event[Object] = Event[Object] or {}
local ObjectEvent = Event[Object]
ObjectEvent[Func] = UserData or true
end
-- 设置调用前回调
function SetDispatchHook( Self, HookFunc )
Self.mPreInvokeFunc = HookFunc
end
-- 派发
function Dispatch( Self, EventName, ... )
assert( EventName )
local Event = Self.mEventTable[ EventName ]
for Object,ObjectFunc in pairs( Event ) do
if Object == "_StaticFunc" then
for Func, UserData in pairs( ObjectFunc ) do
Self.mPreInvokeFunc( EventName, Func, nil, UserData, ... )
end
else
for Func, UserData in pairs( ObjectFunc ) do
Self.mPreInvokeFunc( EventName, Func, Object, UserData, ... )
end
end
end
end
-- 回调是否存在
function Exist( Self, EventName )
assert( EventName )
local Event = Self.mEventTable[ EventName ]
if not Event then
return false
end
-- 需要遍历下map, 可能有事件名存在, 但是没有任何回调的
for Object,ObjectFunc in pairs( Event ) do
for Func, _ in pairs( ObjectFunc ) do
-- 居然有一个
return true
end
end
return false
end
-- 清除
function Remove( Self, EventName, Func, Object )
assert( Func )
local Event = Self.mEventTable[ EventName ]
if not Event then
return
end
if not Object then
Object = "_StaticFunc"
end
local ObjectEvent = Event[Object]
if not ObjectEvent then
return
end
ObjectEvent[Func] = nil
end
-- 清除对象的所有回调
function RemoveObjectAllFunc( Self, EventName, Object )
assert( Object )
local Event = Self.mEventTable[ EventName ]
if not Event then
return
end
Event[Object] = nil
end
这里注意下, 我是将EventDispatcher.lua放置在Core目录下, 因此需要使用require “Core.EventDispatcher”进行调用
使用用例
local EventDispatcher = require 'Core.EventDispatcher'
local E = EventDispatcher.New()
E:Add( "a", function( a, b ) print( a, b ) end )
local Func = function( a ) print( a ) end
E:Add( "a", Func )
E:Dispatch("a", 1, 2 )
print( E:Exist("a"), E:Exist("b"))
E:Remove("a", Func )
E:Dispatch("a", 1, 2 )
print( E:Exist("a"), E:Exist("b"))