使用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 ...
随机推荐
- c++ 之 编译期多态&运行期多态
编译时多态:程序运行前发生的事件 —— 函数重载.运算符重载 .模板 ——静态绑定 运行时多态:程序运行时发生的事件 —— 虚函数机制——动态绑定 template<typename T> ...
- PHP JS JQ 异步上传并立即显示图片
提交页面: <! DOCTYPE html> < html> < head> < meta charset ="GB2312" > ...
- Win7 下IIS(7.5)发布 ASP.NET MVC
操作系统 Win 7 旗舰版 开发工具 VS2015 使用技术 IIS7.5 + MVC4.0 一 . 在IIS上部署程序后出现错误-当前标识(NT AUTHORITY/NETWORK SERVICE ...
- pb自动注册ole控件
方法一: 1.手工注册OCX控件 将该控件随程序一起发布,然后,将此文件拷到windows\system,或者直接放在本运行目录,然后执行dos命令,run( "regsvr32 *. ...
- 中小网站如何使用谷歌Adsence国际化优势赚钱?
劲捷电子信息有限公司是一家拿了美国风险投资的互联网公司.他的创办人祁劲松2005年加入AdSense,迄今收获颇丰,为此他还写了一本 <Google AdSense实战宝典>.在祁劲松看来 ...
- 初次学习shader
Shader "Custom/Diffuse Texture" { //在shader中的位置 Properties { //着色器的属性 _MainTex ("Base ...
- JS总结 本地对象2 BOM DOM
string对象 定义一个字符: var str = "world"; str.length 返回字符长度,5 str.charAt(2) 返回字符串第2个字符(从0开始,下 ...
- 解决 emulator-5554 disconnected! Cancelling
在命令行状态下: adb kill-server ---再adb start-server:
- SE homework2
1. (1) Fault: for循环语句中的条件表达式i > 0,不能检查到数组的第一个元素,应该为 i >= 0 . (2) test:x=[]:y=3 Expected = -1 A ...
- 视音频技术作业一:比较CCD与CMOS摄像的区别
作业详解: CCD与CMOS简介: CCD: CCD是Charge Coupled Device(电荷耦合器件)的缩写,它是一种半导体成像器件,因而具有灵敏度高.抗强光.畸变小.体积小.寿命长.抗震动 ...