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

为了使用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. LoadRunner录制一个登录

    1.点击录制脚本 2.点击左边页面加号

  2. js实现全选反选功能

    开始慢慢地学习js&jQuery. function clicked(){ var arr=document.getElementsByName("product"); f ...

  3. oracle分析函数与over()(转)

    文章参考:http://blog.csdn.net/haiross/article/details/15336313 -- Oracle分析函数入门-- 分析函数是什么? 分析函数是Oracle专门用 ...

  4. windows下安装rabbitmq的php扩展amqp

    最近研究rabbitmq队列,linux安装这样的软件一向都是很方便的,但是windows可能会比较麻烦,所以对windows的安装做个记录. windows上使用的php扩展为dll文件,首先去下载 ...

  5. firefox浏览器中silverlight无法输入问题

    firefox浏览器中silverlight无法输入问题 今天用firefox浏览silverlight网页,想在文本框中输入内容,却没想到silverlight插件意外崩溃了.google一下,发现 ...

  6. 2048游戏C语言代码

    如果程序里面有错误,希望大家能够批评指正! #include<stdio.h> #include<stdlib.h> #include<conio.h> #incl ...

  7. C#正则表达式匹配字符串

    正则表达式可以快速判断所给字符串是否某种指定格式.这里将一些常用的方法封装进一个字符串工具类中. public static class StringTool { /// <summary> ...

  8. 【转】最佳Restful API 实践

    原文转自:https://bourgeois.me/rest/ REST APIs are a very common topic nowaday; they are part of almost e ...

  9. iOS开发 首次启动显示用户引导,第二次启动直接进入App,UIScrollView,UIPageControl,NSUserDefaults

    首先创建一个引导图的控制器类 UserGuideViewController.h和UserGuideViewController.m #import <UIKit/UIKit.h> #im ...

  10. 10——operator=返回reference to *this

    注意operator=返回一个引用,便于连锁赋值