我有一个系统,它使用简单的基于队列的系统来管理多个参与者发生的事件。 Event
是一个简单的类,它有时间和一个抽象方法 fire()
。 Actor
是一个简单的接口(interface),它实现了两个方法 - think()
和 act()
。每个参与者都有 2 个基本事件,其实现方式如下:
public class ActorThinkEvent extends Event {
private Actor actor;
public ActorThinkEvent(Actor actor, long time) {
super(time);
this.actor = actor;
}
public void fire() {
Main.game.queue.add(actor.think());
}
}
public abstract class ActorActEvent extends Event {
protected Actor actor;
protected ActorActEvent(Actor actor, long time) {
super(time);
this.actor = actor;
}
public void fire() {
long spent = act();
Main.game.queue.add(new ActorThinkEvent(actor, time + spent));
}
public abstract long act();
}
这样,“思考”调用就被修复了,它应该生成一个 ActorActEvent
并将其添加到全局队列中,而“行动”调用则使用基于自定义 ActorActEvent 的类来完成实现该操作,仅返回所花费的时间,并且新的“思考”事件将自动添加到队列中。
我在这里看到的问题是,基于 ActorActEvent 的类的实现归结为从 ActorActEvent.act()
到带有预定义的 Actor
类的某些方法的简单委托(delegate)存储的参数,即我的所有 ActEvent 类看起来都非常相似:
public class ActorMoveEvent extends ActorActEvent {
private Coords delta;
public ActorMoveEvent(Actor actor, long time, Coords delta) {
super(actor, time);
this.delta = delta;
}
public long act() {
return actor.moveBy(delta);
}
}
public class ActorReloadEvent extends ActorActEvent {
public ActorReloadEvent(Actor actor, long time) {
super(actor, time);
}
public long act() {
return actor.reload();
}
}
public class ActorPickupEvent extends ActorActEvent {
private ItemStash wantedItems;
public ActorPickupEvent(Actor actor, long time, ItemStash wantedItems) {
super(actor, time);
this.wantedItems = wantedItems;
}
public long act() {
return actor.pickupItems(wantedItems);
}
}
我可能最终会得到几十个这样的类(class)。如果我理解正确的话,这是 Command pattern 的经典实现。但是,我对所有这些委托(delegate)类感觉不太好,尤其是手动编写它们。
我想到使用Java的反射和诸如Method.invoke()之类的东西,但是,在通用 ActorActEvent
类中向其传递 Method
实例和预存储参数时,速度会相当慢。我想过为所有这些类编写一个生成器,但对我来说,它看起来是一个相当笨拙的解决方案。
如果它是某种现代脚本/函数式语言,我最终会使用类似 block /闭包的结构,首先准备它并在需要时调用它。唉,我不知道如何在 Java 中高效地实现它。
对于我能做些什么来改善这种情况有什么好主意吗?
最佳答案
我的建议是走反射(reflection)之路。在这种情况下,担心“速度会相当慢”还为时过早。反射的性能在过去十年中已经相当不错,您将能够缓存 Method
对象以节省重新解析名称所花费的时间(这可能是最大的性能损失)。这种方法实现起来灵活且快速。
如果您真的喜欢闭包,您可以为您的事件尝试匿名内部类。有一些限制 - 您仍然需要声明您的方法,因此它有点冗长,并且您需要将变量声明为 Final 以便从内部类中访问它们。这种方法将为您提供静态类型的所有性能和安全性,但您仍然必须为每个事件都有一个类。
从历史上看,事件表现出“两全其美”的行为,并在对象
之间传递,依赖于目标知道如何转换和处理它们。
关于Java设计模式: event system,给定参与者的多个操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4642307/