设计一个简单的事件派发器,个人觉得最重要的一点就是如何保证事件派发过程中,添加或删除同类事件,不影响事件迭代顺序和结果,只要解决这一点,其它都好办。

为了使用pairs遍历函数,重写了pairs(lua 5.2以上版本不需要):

stdext.lua

local _ipairs = ipairs
function ipairs(t)
local mt = getmetatable(t)
if mt and mt.__ipairs then
return mt.__ipairs(t)
end return _ipairs(t)
end local _pairs = pairs
function 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 = debug
local string = string
local print = print local util = {} function util.trace(prefix)
prefix = prefix .. " "
return function(...)
print(prefix .. string.format(...))
end
end function util.callee()
return debug.getinfo(, "f").func
end function util.getupvalues(func)
local u = {}
local i =
while true do
i = i +
local key, value = debug.getupvalue(func, i)
if key then
u[key] = value
else
break
end
end return u
end return util

EventDispatcher.lua

local util = require "util"
local class = require "class" local trace = util.trace("[EventDispatcher]")
local assert = assert
local next = next
local pairs = pairs local ANONYMOUS = {}
local hashlist = {} local EventDispatcher = class("EventDispatcher") function EventDispatcher:ctor()
self._listeners = {}
end function 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)
end function 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
end
end function 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
end
end function EventDispatcher:hasEventListener(event)
return self._listeners[event] ~= nil
end -------------------------------------------------------------------------------
-- hashlist
--
-------------------------------------------------------------------------------
local tostring = tostring
hashlist.__index = hashlist local function makeindex(owner, handler)
return tostring(owner) .. "|" .. tostring(handler)
end function hashlist.new()
local self = setmetatable({}, hashlist)
self.header = {}
self.header.next = self.header
self.header.prev = self.header
self.entries = {}
return self
end local function itor(header, current)
local entry = current.next
if entry ~= header then
return entry, entry.key, entry.value
end
end function hashlist:__pairs()
return itor, self.header, self.header
end function hashlist:insert(key, value, priority)
local idx = makeindex(key, value) if self.entries[idx] then return end local entry = {key = key, value = 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] = entry
end function hashlist:empty()
return next(self.entries) == nil
end function 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
end
end return EventDispatcher

示例:

local class = require "class"
local EventDispatcher = require "EventDispatcher" local A = class("A", EventDispatcher) function A:ctor()
self:addEventListener("test", self.testHandler, self)
end function A:testHandler()
print("test in testHandler")
end local 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, ) a:dispatchEvent("test", "a", "b")
a:dispatchEvent("test", "a", "b")

使用lua实现一个简单的事件派发器的更多相关文章

  1. Unity-自定义事件派发器的两次尝试

    一.前言: 在游戏开发的很多时候,需要引用其他类的方法,但是一旦类多起来了,相互引用会导致引用关系混乱,极其难以阅读. 以前初次做抖音小游戏时,和一位经验老道的cocos程序员合作,看到我写的代码他不 ...

  2. 48、[源码]-Spring容器创建-初始化事件派发器、监听器等

    48.[源码]-Spring容器创建-初始化事件派发器.监听器等 8.initApplicationEventMulticaster();初始化事件派发器: 获取BeanFactory 从BeanFa ...

  3. Arachnid包含一个简单的HTML剖析器能够分析包含HTML内容的输入流

    Arachnid是一个基于Java的web spider框架.它包含一个简单的HTML剖析器能够分析包含HTML内容的输入流.通过实现Arachnid的子类就能够开发一个简单的Web spiders并 ...

  4. 自己动手实现一个简单的JSON解析器

    1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...

  5. 使用Python制作一个简单的刷博器

    呵呵,不得不佩服Python的强大,寥寥几句代码就能做一个简单的刷博器. import webbrowser as web import time import os count=0 while co ...

  6. 一个简单的json解析器

    实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...

  7. 用c#自己实现一个简单的JSON解析器

    一.JSON格式介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着很多优点.例如易读性更好,占用空间更 ...

  8. Java实现一个简单的事件监听器

    关于事件监听我们需要知道的一些基础知识. a)事件三要素(who when what): source -- 事件源 when -- 事件发生时间 message -- 事件主题消息,即希望通过事件传 ...

  9. Objective-C ,ios,iphone开发基础:快速实现一个简单的图片查看器

    新建一个single view 工程: 关闭ARC , 在.xib视图文件上拖放一个UIImageView  两个UIButton ,一个UISlider ,布局如图. 并为他们连线, UIImage ...

随机推荐

  1. Java泛型学习笔记 - (一)泛型的介绍

    一.什么是泛型:泛型的作用是用来规定一个类, 接口或方法所能接受的数据的类型. 就像在声明方法时指定参数一样, 我们在声明一个类, 接口或方法时, 也可以指定其"类型参数", 也就 ...

  2. ov5648摄像头调试

    工作平台:MTK8389 sensor:ov5648 今天调试这颗摄像头的心得就是:首先得把上电时序弄对,I2C才能通讯,然后就是ID都要写对.

  3. zip压缩命令的使用

    file命令可以查看文件的类型 tar类型 .tar gzip类型   .gz  bzip2类型  .bz2 zip类型    .zip 如果一个压缩文件由tar命令解压的前提,2个条件 1.这个文件 ...

  4. SpringMVC 对比 struts2

    一.SpringMVC的入口是Servlet,而struts2的入口是filter 二.SpringMVC会稍微比struts2 快些.SpringMVC是基于方法设计的,而struts2是基于类,每 ...

  5. taginput ,complete使用笔记

    页面用到自动完成功能及需要taginput控件去展示,查资料的过程中发现 有两个类似的jQuery类库,到现在我也没搞明白它们两个有啥关联,jquery.tagsinput.js和bootstrap- ...

  6. 使用NFC读卡器ACR122u读取银行卡信息

    使用NFC读卡器  ACR122u 使用ACR122u Tool 软件发送spdu指令即可 一些运行结果 如上所示,银行卡的卡号,有效期,卡主姓名,身份证号,进期消费记录均可读出

  7. 解决:j-link V8下载器灯不亮,无法正常烧写固件

    昨天j-link V8下载仿真F4正常,下午下载仿真F1后吃了个饭,然后它的灯就不亮了...按照这个例程弄了好几遍都不行,http://www.cr173.com/soft/98542.html,卡在 ...

  8. IntelliJ IDEA注册码

    1.打开IJ,help选项下的register 2. 选择Activation code 将注册码粘到内容框里,点击ok即可 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QT ...

  9. oracle xmltype导入并解析Excel数据 (四)特别说明

    1.Excel导出,此处没有给出 2.错误原因在中间表,T_EXCEL_IMPORT_GENERATION,其中errormsg不为空的数据 3,中间表入库过程: 需要自己实现,为一个存储过程,存储过 ...

  10. codeforces 734E(DFS,树的直径(最长路))

    题目链接:http://codeforces.com/contest/734/problem/E 题意:有一棵黑白树,每次操作可以使一个同色连通块变色,问最少几次操作能使树变成全黑或全白. 思路:先进 ...