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

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

stdext.lua

local _ipairs = ipairs
function ipairs(t)local mt = getmetatable(t) if mt and mt.__ipairs thenreturn mt.__ipairs(t)endreturn _ipairs(t)
endlocal _pairs = pairs
function pairs(t)local mt = getmetatable(t)if mt and mt.__pairs thenreturn mt.__pairs(t)endreturn _pairs(t)
end

util.lua

require "stdext"local debug = debug
local string = string
local print = printlocal util = {}function util.trace(prefix)prefix = prefix .. " "return function(...)print(prefix .. string.format(...))end
endfunction util.callee()return debug.getinfo(2, "f").func
endfunction util.getupvalues(func)local u = {}local i = 0while true doi = i + 1local key, value = debug.getupvalue(func, i)if key thenu[key] = valueelsebreakendendreturn u
endreturn util

EventDispatcher.lua

local util = require "util"
local class = require "class"local trace = util.trace("[EventDispatcher]")
local assert = assert
local next = next
local 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 thenlist = hashlist.new()self._listeners[event] = listendlist:insert(owner or ANONYMOUS, listener, priority)
endfunction EventDispatcher:removeEventListener(event, listener, owner)assert(event)assert(listener)local list = self._listeners[event]if list thenlist:remove(owner or ANONYMOUS, listener)if list:empty() thenself._listeners[event] = nilendend
endfunction EventDispatcher:dispatchEvent(event, ...)assert(event, "event type is nil")if self:hasEventListener(event) thenfor _, owner, listener in pairs(self._listeners[event]) doif owner == ANONYMOUS thenlistener(self, ...)elselistener(owner, self, ...)endendend
endfunction EventDispatcher:hasEventListener(event)return self._listeners[event] ~= nil
end-------------------------------------------------------------------------------
-- hashlist
--
-------------------------------------------------------------------------------
local tostring = tostring
hashlist.__index = hashlistlocal function makeindex(owner, handler)return tostring(owner) .. "|" .. tostring(handler)
endfunction hashlist.new()local self = setmetatable({}, hashlist)self.header = {}self.header.next = self.headerself.header.prev = self.headerself.entries = {}return self
endlocal function itor(header, current)local entry = current.nextif entry ~= header thenreturn entry, entry.key, entry.valueend
endfunction hashlist:__pairs()return itor, self.header, self.header
endfunction hashlist:insert(key, value, priority)local idx = makeindex(key, value)if self.entries[idx] then return endlocal entry = {key = key, value = value, priority = priority}local header, current = self.headerif not priority thencurrent = header.prevelsecurrent = headerlocal next = current.nextwhile next ~= header doif not next.priority or priority <= next.priority thenbreakelsecurrent = nextnext = current.nextendendendentry.next = current.nextentry.prev = currentcurrent.next.prev = entrycurrent.next = entryself.entries[idx] = entry
endfunction hashlist:empty()return next(self.entries) == nil
endfunction hashlist:remove(key, value)local idx = makeindex(key, value)local entry = self.entries[idx]if entry thenentry.prev.next = entry.nextentry.next.prev = entry.prevself.entries[idx] = nilend
endreturn 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")

转载于:https://www.cnblogs.com/zhongfq/p/4178043.html

使用lua实现一个简单的事件派发器相关推荐

  1. 用Qt写一个简单的音乐播放器(三):增加界面(播放跳转与音量控制)

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

  2. cocos 的EventHandler 事件派发器

    cocos 的EventHandler 事件派发器 cc.Component.EventHandler 类 官方说明 "EventHandler" 类用来设置场景中的事件回调,该类 ...

  3. 如何使用aframe.js构建一个简单的VR播放器

    在当今这个信息化的时代,虚拟现实(VR)已经开始逐渐成为一种新的生活方式.作为一名前端开发工程师,在学习和探索VR技术方面,aframe.js是一个非常有趣和有用的工具.在本文中,我将介绍如何使用af ...

  4. 用Qt写一个简单的音乐播放器(四):歌曲浏览、上一曲、下一曲

    一.前言 在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐. 在用Qt写一个简单的音乐播放器(二):增加界面(开始和 ...

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

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

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

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

  7. json string 格式_自己动手实现一个简单的JSON解析器

    作者:田小波 原文:http://cnblogs.com/nullllun/p/8358146.html 1. 背景 JSON(JavaScript Object Notation) 是一种轻量级的数 ...

  8. GStreamer 编写一个简单的MP3播放器

    本文介绍如何使用GStreamer 编写一个简单的MP3播放器. 1,需要使用mad解码插件,因此需要先安装gstreamer0.10-plugins-ugly 2,编写mp3播放器 下面来看看如何利 ...

  9. python实现雪花动态图_如何通过雪花算法用Python实现一个简单的发号器

    实现一个简单的发号器 根据snowflake算法的原理实现一个简单的发号器,产生不重复.自增的id. 1.snowflake算法的简单描述 这里的snowflake算法是用二进制的,有64位.其中41 ...

最新文章

  1. iPhone应用程序图标 - 精确半径?
  2. object-c html,object.html
  3. 你不得不了解 Helm 3 中的 5 个关键新特性
  4. 两个链表生成相加链表
  5. [respberry pi3][suse] 配置docker
  6. 开始学习VS2008+.net3.5咯 :)
  7. java jdbc开启事务_spring jdbc 事务配置
  8. k8s核心技术-Service概述_Service如何实现负载均衡_提供虚拟IP_以及Po的IP注册和发现---K8S_Google工作笔记0031
  9. mariadb multi-source replication(mariadb多主复制)
  10. [转载] 动态口令,动态密码生成(OTP)
  11. yum与apt-get的区别以及两者更新源(阿里/网易【163】)
  12. Pattern 模式器: Matcher 匹配器
  13. Gradle基础教程
  14. 中图杯获奖作品计算机组,中图杯大赛试卷
  15. 微信企业号已停止提供企业消息会话服务器,企业微信注册时显示会话服务已经被安装了怎么解决 解决攻略教程大全...
  16. Chromium for mac(谷歌浏览器)V89.0.4336.0官方最新版
  17. 视频通话和直播技术webRTC和RTMP探究
  18. 【第1天】移动App-学习笔记
  19. Android针对IC卡读写的NFC开发
  20. 基于JAVA干洗店订单管理系统设计与实现计算机毕业设计源码+数据库+lw文档+系统+部署

热门文章

  1. excel调用python编程-使用Python对Excel进行读写操作
  2. python入门教程书-清华大学出版社-图书详情-《Python快速入门精讲》
  3. python官方网站是-Python基础
  4. NVIDIA Jetson 系列产品开发相关文档,TAO、TLT、NGC
  5. Vmware虚拟机安装Ubuntu 16.04 LTS(长期支持)版本+VMware tools安装
  6. EnableFeignClients注解解析
  7. libevent中的缓冲区(一)
  8. TextSwitcher的使用(一)
  9. Service概念及用途
  10. SVN commit:remains in tree-conflict错误的解决办法