Lua実装イベントディスパッチ

17227 ワード

モジュール間の結合を低減するために、多くのシステムはイベント配布メカニズムを使用し、受信者は配布者が誰であるかを知る必要はない.Qtでは、このシステムをSlot&Signalと呼ぶ、mocコードの生成メカニズムに合わせる必要があるが、システム自体はスレッドが安全である.
ここではluaのイベント配布メカニズムについて議論します.私はこれをluaモジュールと書いて、cocos 2 dxと協力して論理処理を行うのに便利です.
 
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"))