Answers:
您应该有一组定义明确的接口,允许它们传输或接收消息-为它们提供对EventScheduler的引用应该很简单。如果不是这样,或者如果您感觉那样涉及将事件调度程序传递给“太多”的不同类型,那么您可能会遇到更大的设计问题(混杂的依赖性,单身人士会加剧这种情况,而不是解决) )。
请记住,尽管将调度程序传递给需要的接口的技术是“ 依赖注入 ”的一种形式,但是在这种情况下,您并不是要注入新的依赖。这是系统中已经存在的依赖关系,但是现在您将其设为显式依赖关系(与单例的隐式依赖关系相比)。根据经验,显式依赖项更可取,因为它们更易于记录。
您还可以通过将事件调度的使用者彼此分离(因为它们不一定都绑定到同一调度程序)来提供更大的灵活性,这对于测试或模拟本地客户端/服务器设置或许多其他选项很有用-您可能不需要这些其他选项,但是您没有花费任何精力来人为地限制自己使用它们,这是一个优点。
编辑:当我谈论传递调度程序时,我的意思是:如果您有负责响应碰撞的游戏组件,则可能是通过某些碰撞响应器工厂创建的,该工厂是物理层的一部分。如果使用调度程序实例构造工厂,则工厂可以将该实例传递给它创建的任何响应者,然后可以利用它引发事件(或订阅其他事件)。
class CollisionResponderFactory {
public CollisionResponderFactory (EventScheduler scheduler) {
this.scheduler = scheduler;
}
CollisionResponder CreateResponder() {
return new CollisionResponder(scheduler);
}
EventScheduler scheduler;
}
class CollisionResponder {
public CollisionResponder (EventScheduler scheduler) {
this.scheduler = scheduler;
}
public void OnCollision(GameObject a, GameObject b) {
if(a.IsBullet) {
scheduler.RaiseEvent(E_BIG_EXPLOSION);
}
}
EventScheduler scheduler;
}
这显然是一个非常人为和简化的示例,因为我不知道您的游戏对象模型是什么。但是,它确实说明了对事件调度程序的依赖关系的显式表示,并显示了进一步封装的潜力(如果响应程序以与概念相同的概念级别与更高级别的冲突响应系统进行通信,则不必将响应程序传递给响应程序。通过调度程序处理引发事件的细节的工厂,这会将每个单独的响应程序实现与事件分发系统的实现详细信息隔离开来,例如在碰撞时引发哪个特定事件,这可能是您的系统的理想选择- - 或不)。
我也倾向于避免单例,但是有一些对象最有意义,因为单例和中央消息传递系统就是其中之一。尽管我听到过很多抱怨,但单例确实比全局变量/函数要好得多,因为您总是必须刻意解决它(而全局值只是凭空魔术般地出现了)。
最后,每个消息发送者和接收者都必须有一个公共的交点,并且最好让所有事物共享一个公共的单例来使对象分离,而不是让每个消息发送者直接了解消息接收者。
虽然我确定可以为您的事件系统设计其他一些体系结构,但对我来说,似乎过于浪费精力了,尤其是在使用事件系统已成为不使用事件系统的重大胜利时。
编辑:至于您在定期触发器上调度的爆炸事件的特定示例,我可能会将事件调度在其他一些对象(例如转塔炮或引起这些爆炸的物体)上,而不是在中央事件系统中调度。但是,这些事件仍将分派到中央事件系统。