使用lua实现一个简单的事件派发器
设计一个简单的事件派发器,个人觉得最重要的一点就是如何保证事件派发过程中,添加或删除同类事件,不影响事件迭代顺序和结果,只要解决这一点,其它都好办。
为了使用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实现一个简单的事件派发器的更多相关文章
- Unity-自定义事件派发器的两次尝试
一.前言: 在游戏开发的很多时候,需要引用其他类的方法,但是一旦类多起来了,相互引用会导致引用关系混乱,极其难以阅读. 以前初次做抖音小游戏时,和一位经验老道的cocos程序员合作,看到我写的代码他不 ...
- 48、[源码]-Spring容器创建-初始化事件派发器、监听器等
48.[源码]-Spring容器创建-初始化事件派发器.监听器等 8.initApplicationEventMulticaster();初始化事件派发器: 获取BeanFactory 从BeanFa ...
- Arachnid包含一个简单的HTML剖析器能够分析包含HTML内容的输入流
Arachnid是一个基于Java的web spider框架.它包含一个简单的HTML剖析器能够分析包含HTML内容的输入流.通过实现Arachnid的子类就能够开发一个简单的Web spiders并 ...
- 自己动手实现一个简单的JSON解析器
1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着诸多优点.比如易读性更好,占用空间更少等.在 ...
- 使用Python制作一个简单的刷博器
呵呵,不得不佩服Python的强大,寥寥几句代码就能做一个简单的刷博器. import webbrowser as web import time import os count=0 while co ...
- 一个简单的json解析器
实现一个简单地json解析器. 两部分组成,词法分析.语法分析 词法分析 package com.mahuan.json; import java.util.LinkedList; import ja ...
- 用c#自己实现一个简单的JSON解析器
一.JSON格式介绍 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.相对于另一种数据交换格式 XML,JSON 有着很多优点.例如易读性更好,占用空间更 ...
- Java实现一个简单的事件监听器
关于事件监听我们需要知道的一些基础知识. a)事件三要素(who when what): source -- 事件源 when -- 事件发生时间 message -- 事件主题消息,即希望通过事件传 ...
- Objective-C ,ios,iphone开发基础:快速实现一个简单的图片查看器
新建一个single view 工程: 关闭ARC , 在.xib视图文件上拖放一个UIImageView 两个UIButton ,一个UISlider ,布局如图. 并为他们连线, UIImage ...
随机推荐
- mysql 导出导入数据库
导入mysql -u$USER -p$PASSWD -h127.0.0.1 -P3306 --default-character-set=utf8 < db.all.sql导出 mysqldum ...
- git clone错误
git clone错误 Initialized empty Git repository in ***/.git/ error: The requested URL returned error: 4 ...
- ObjC宏定义小细节
Macros A definition that takes arguments, particularly more than one, is often known as a macro: #de ...
- 使用 IDEA + Maven + Git 快速开发 JAVA或者Web 应用(转)
0-0 前言 最近和同事做爬虫,其中我主要遇到的问题是:同事在github上放了爬虫demo让我自己去下载,然后自己能搭好环境让整个项目跑起来去抓51job找工作数据.git上克隆一个项目下来,项目是 ...
- Ubuntu14.04安装build-essential失败,包依赖问题如何解决?
正在读取软件包列表... 完成 正在分析软件包的依赖关系树 正在读取状态信息... 完成 有一些软件包无法被安装.如果您用的是 unstable 发行版,这也许是 因为系统 ...
- 关于eclipse中DDMS中Emulator Control选项卡为灰色不可用
首先先感谢版主:http://blog.csdn.net/noname666/article/details/51670905#reply 方法一的出处:http://stackoverflow.co ...
- Java标识符和关键字
一.标识符 概念:就是用于给程序中的变量.类.方法命名的符号; 标识符规则:标识符可以有字母.数字.下划线_.和美元符号$组成,并且数字不能打头 ...
- 【Learning Python】【第四章】Python代码结构(一)
这一章的主旨在于介绍python的代码结构 缩进 在很多的编程语言中,一般{}用于控制代码块,比如以下的一段C代码 if(var <= 10) { printf("....." ...
- 从csv文件导数据到MySQL
导入: load data local infile 'D:\\top-1m.csv' (注意要加上local)10.21.into table `site` fields terminated ...
- CPU指令集
cpu作为一台电脑中的核心,它的作用是无法替代的.而cpu本身只是在块硅晶片上所集成的超大规模的集成电路,集成的晶体管数量可达到上亿个,是由非常先进复杂的制造工艺制造出来的,拥有相当高的科技含量. C ...