首页 > 代码库 > 使用lua实现一个简单的事件派发器
使用lua实现一个简单的事件派发器
设计一个简单的事件派发器,个人觉得最重要的一点就是如何保证事件派发过程中,添加或删除同类事件,不影响事件迭代顺序和结果,只要解决这一点,其它都好办。
为了使用pairs遍历函数,重写了pairs(lua 5.2以上版本不需要):
stdext.lua
local _ipairs = ipairsfunction ipairs(t) local mt = getmetatable(t) if mt and mt.__ipairs then return mt.__ipairs(t) end return _ipairs(t)endlocal _pairs = pairsfunction pairs(t) local mt = getmetatable(t) if mt and mt.__pairs then return mt.__pairs(t) end return _pairs(t)end
util.lua
require "stdext"local debug = debuglocal string = stringlocal print = printlocal util = {}function util.trace(prefix) prefix = prefix .. " " return function(...) print(prefix .. string.format(...)) endendfunction util.callee() return debug.getinfo(2, "f").funcendfunction util.getupvalues(func) local u = {} local i = 0 while true do i = i + 1 local key, value = http://www.mamicode.com/debug.getupvalue(func, i) if key then u[key] = value else break end end return uendreturn util
EventDispatcher.lua
local util = require "util"local class = require "class"local trace = util.trace("[EventDispatcher]")local assert = assertlocal next = nextlocal pairs = pairslocal ANONYMOUS = {}local hashlist = {}local EventDispatcher = class("EventDispatcher")function EventDispatcher:ctor() self._listeners = {}endfunction EventDispatcher:addEventListener(event, listener, owner, priority) assert(event) assert(listener) local list = self._listeners[event] if not list then list = hashlist.new() self._listeners[event] = list end list:insert(owner or ANONYMOUS, listener, priority)endfunction EventDispatcher:removeEventListener(event, listener, owner) assert(event) assert(listener) local list = self._listeners[event] if list then list:remove(owner or ANONYMOUS, listener) if list:empty() then self._listeners[event] = nil end endendfunction EventDispatcher:dispatchEvent(event, ...) assert(event, "event type is nil") if self:hasEventListener(event) then for _, owner, listener in pairs(self._listeners[event]) do if owner == ANONYMOUS then listener(self, ...) else listener(owner, self, ...) end end endendfunction EventDispatcher:hasEventListener(event) return self._listeners[event] ~= nilend--------------------------------------------------------------------------------- hashlist---------------------------------------------------------------------------------local tostring = tostringhashlist.__index = hashlistlocal function makeindex(owner, handler) return tostring(owner) .. "|" .. tostring(handler)endfunction hashlist.new() local self = setmetatable({}, hashlist) self.header = {} self.header.next = self.header self.header.prev = self.header self.entries = {} return selfendlocal function itor(header, current) local entry = current.next if entry ~= header then return entry, entry.key, entry.value endendfunction hashlist:__pairs() return itor, self.header, self.headerendfunction hashlist:insert(key, value, priority) local idx = makeindex(key, value) if self.entries[idx] then return end local entry = {key = key, value = http://www.mamicode.com/value, priority = priority} local header, current = self.header if not priority then current = header.prev else current = header local next = current.next while next ~= header do if not next.priority or priority <= next.priority then break else current = next next = current.next end end end entry.next = current.next entry.prev = current current.next.prev = entry current.next = entry self.entries[idx] = entryendfunction hashlist:empty() return next(self.entries) == nilendfunction hashlist:remove(key, value) local idx = makeindex(key, value) local entry = self.entries[idx] if entry then entry.prev.next = entry.next entry.next.prev = entry.prev self.entries[idx] = nil endendreturn EventDispatcher
示例:
local class = require "class"local EventDispatcher = require "EventDispatcher"local A = class("A", EventDispatcher)function A:ctor() self:addEventListener("test", self.testHandler, self)endfunction A:testHandler() print("test in testHandler")endlocal a = A.new()a:addEventListener("test", function() a:removeEventListener("test", util.callee()) print("test outside")end)a:addEventListener("test", function() print("test priority")end, nil, 0)
a:dispatchEvent("test", "a", "b")
a:dispatchEvent("test", "a", "b")
使用lua实现一个简单的事件派发器
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。