仓库
仓库链接:EventReactor: 一种依靠优先级责任链和回调实现的事件中心,使用接口对权限进行隔离。
仓库里面有一些详细说明,本文只从概念上谈一谈。
前言
又造轮子了。
其他的事件中心用得不顺手,总感觉和单例区分不开。
之前用过一个魔改的框架阿巴阿巴/MeowFramework,它的事件给我的感觉就是,太自由了,每个对象的权限都特别大,以至于不知道该干什么。
还有就是,它的实现是写在事件里面的,结果造成我为了解耦去发事件,事件里面可能反而又去调用单例(因为这个框架本身不是纯粹的事件中心,它支持单例),总有种多此一举的感觉。
更难受的是,这样把实现全部拆散到零零散散的众多事件当中,一个事件调用(耦合)另外几个事件,结果就是根本搞不清楚一个事件从哪来(哪个事件发起它的),到哪去(会引发什么事件)。
轮子
就像给一堆内存定下一个“类型”一样,限制与便利只在一念之间。用接口进行权限隔离也是老生常谈的话题了。我做的事件中心就很简单,除去模块中心(只有初始化时用到它)以外只有三种对象:模块,交互器和事件。我理想中的事件简单又纯粹,只包含数据,不包括任何逻辑,怎么做完全由监听者决定。
模块,就是原先单例模式中的各个单例类。交互器是我自创的概念,原意是指那些能够主动发起新流程的实体对象,例如某个UI按钮,又例如AI小怪,一个能源源不断地产生黄色小球的东西等。从程序的输入-输出的角度看,交互器就是输入端。我固执地认为玩家和AI只是输入端不同而已,必须走同一套处理流程。AI能体验到的玩家也必须要能体验到,反之亦然。
模块和交互器的权限被严格限制。再加上事件的种类不多——我一共只划分出三个种类:请求、结果和查询,哪一步要做什么就很清楚了。结果事件不能被主动发起,其作为请求事件内嵌的一个数据存在,只能在请求事件结束后被顺带发送。由于事件本身没有多大意义,真正需要关注的只有模块和交互器而已。
我是这么认为的:凡是要进行某种操作,其都有成功和失败之分——因此不存在单纯的”命令“,只有”请求“。凡是要公布某种现状,其都必然来自于某种操作——因此不存在单纯的”通知“,只有”结果“。进行某种请求是有副作用的(即使是读,如果没有相应对象,也要加载或创建一个),与之相对,进行某种查询一定是没有副作用的。总结下来,绝大多数事情都能用这简单的三种事件概括。
两种关注对象,三种事件,构成了整个事件中心。要说限制,确实限制得挺狠;要说自由,这一套监听机制也足够自由。增加或删除一个模块,对原有代码的影响不大。因为全流程都走的有优先级事件,甚至可以让Buff模块去影响背包模块,或着干脆在不动原有代码的基础上直接改成一个新游戏——当然,如果要安全,就当我没说。
缺点
有利有弊,至少设计这一套的时候挺痛苦的,反复修改了不少次。其次就是使用负担,没接触过的人恐怕不太好上手。第三就是代码量,原来一行代码完成的事情现在可能需要一个事件,一个监听,一个发送配合才能完成。好处是就算直接注释掉一个模块,剩下的都能正常运行。不再有那种疯狂的方法层层中转,改一个签名报错几十处存在了。
文章版权归作者所有





暂无评论内容