事件系统的设计

   

local events = {}
local eventHandleId = 0
local eventHandles = {}

local function AddListener(name, listener)
    local listeners = events[name]
    if not listeners then
        --listeners不再是一个简单的table,通过多个标识符来标识
        listeners = { insert = {}, dirty = false, executing = false, destroyed = false }
        events[name] = listeners
    end

    local handleId = listeners[listener] or listeners.insert[listener]
    if not handleId then
        handleId = eventHandleId + 1
        eventHandleId = handleId
        --如果在塞入的时候,该listeners正在被触发,则不执行立即塞入的操作,等下一个触发到来的时候执行
        if listeners.executing then
            listeners.insert[listener] = handleId
            listeners.dirty = true
        else
            listeners[listener] = handleId
        end
        eventHandles[handleId] = { name, listener }
    end

    return handleId
end

local function RemoveListener(name, listener, handles)
    local listeners = events[name]
    if listeners then
        if not listener then
            for _, handleId in pairs(listeners) do
                eventHandles[handleId] = nil
                if handles then
                    handles[handleId] = nil
                end
            end
            --标记其已经destroyed
            listeners.destroyed = true
            events[name] = nil
        else
            local handleId = listeners[listener] or listeners.insert[listener]
            if handleId then
                listeners[listener] = nil
                listeners.insert[listener] = nil
                eventHandles[handleId] = nil
                if handles then
                    handles[handleId] = nil
                end
            end
        end
    end
end

local function RemoveHandle(handleId)
    local entry = eventHandles[handleId]
    if entry then
        RemoveListener(entry[1], entry[2])
    end
end

local EventManager = {}

function EventManager.Add(name, listener)
    AddListener(name, listener)
end

function EventManager.Remove(name, listener)
    RemoveListener(name, listener)
end

function EventManager.Clear()
    events = {}
    eventHandles = {}
end

function EventManager.Dispatch(name, ...)
    local listeners = events[name]
    if listeners then
        listeners.executing = true
        for listener, _ in pairs(listeners) do
            if type(listener) == "function" then
                listener(name, ...)
            end
            --可能在执行listener的过程中回调执行了remove,所以需要检测一次是否退出
            if listeners.destroyed then
                return
            end
        end
        --触发完后,再执行缓存的塞入检测
        if listeners.dirty then
            for listener, handleId in pairs(listeners.insert) do
                listeners[listener] = handleId
                listeners.insert[listener] = nil
            end
            listeners.dirty = false
        end
        listeners.executing = false
    end
end

 

 

 

 

 

 

 

using System;
using System.Collections.Generic;

public class EventListener
{
    public string    name;
    public Delegate  action;
}

public static class EventManger
{
    private static Dictionary<string, List<EventListener>> listenList = new Dictionary<string, List<EventListener>>();
    private static Dictionary<string, int> listenerStatus = new Dictionary<string, int>();
    private static Dictionary<string, List<EventListener>> addList = new Dictionary<string, List<EventListener>>();
    private static Dictionary<string, List<EventListener>> removeList = new Dictionary<string, List<EventListener>>();

    //查找监听
    public static EventListener GetListener(string name, Delegate action)
    {
        if (action == null) return null;
        List<EventListener> listEvent = null;
        if (!listenList.TryGetValue(name, out listEvent) || listEvent.Count < 1)
            return null;
        var ls = listEvent.Find(l => l.action.Method == action.Method);
        return ls;
    }

    //添加事件监听
    public static EventListener AddEventListener(string name, Delegate action)
    {
        if (action == null) return null;
        //判断是否已经有
        var listener = GetListener(name, action);
        if (listener != null)
            return listener;
        //new 可以用资源池代替
        listener = new EventListener();
        listener.name = name;
        listener.action = action;
        //第一次创建,则建立对应的dic
        if(!listenList.ContainsKey(name))
        {
            listenList.Add(name, new List<EventListener>());
            addList.Add(name, new List<EventListener>());
            removeList.Add(name, new List<EventListener>());
            listenerStatus.Add(name, 0);
        }
        //处于事件触发,则滞后处理
        if (listenerStatus[name] > 0)
            addList[name].Add(listener);
        else
            listenList[name].Add(listener);

        return listener;
    }

    //删除事件监听
    public static void RemoveListener(string name, EventListener listener)
    {
        List<EventListener> deleteList = null;
        if(listenList.TryGetValue(name, out deleteList))
        {
            //首先删除addList中的监听
            addList[name].Remove(listener);
            if(deleteList.Contains(listener))
            {
                //如果正在触发,则滞后
                if (listenerStatus[name] > 0)
                    removeList[name].Add(listener);
                else
                {
                    deleteList.Remove(listener);
                    //归还到资源池去........
                }
            }
        }
    }

    //事件触发
    public static void DispatchEvent(string name)
    {
        //...............
        List<EventListener> ls = null;
        if(listenList.TryGetValue(name, out ls))
        {
            //标记正在触发
            listenerStatus[name]++;
            //
            foreach(var listener in ls)
            {
                listener.action.DynamicInvoke(null);
            }

            var count = listenerStatus[name] - 1;
            listenerStatus[name] = count;
            //此时执行滞后的增删操作
            if(count < 1)
            {
                var list = addList[name];
                ls.AddRange(list);
                list.Clear();
                list = removeList[name];
                foreach (var listener in list)
                    ls.Remove(listener);
                list.Clear();
            }
            //.......
        }
    }

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值