简介
我正在使用实体组件系统处理应用程序。系统在很大程度上依赖于两个抽象类,即组件和处理器,它们共享一对一的关系。每个Processor实现一个基本的Subscriber接口,允许EventManager类在创建新事件时通知它们。
事件
我有一个Event抽象类,它存储事件类型ID,如下所示:
public abstract class Event {
public static final int NONE = 0;
private final int eventID;
public Event(int eventID) {
this.eventID = eventID;
}
public int getEventID() {
return eventID;
}
}
然后我有一个扩展Event的Factory类,如下所示:
public abstract class BaseEvents extends Event {
public static final int TRANSFORM = 1;
public BaseEvents(int eventID) {
super(eventID);
}
public static class Transform extends BaseEvents {
private final float rotation,
tx,
ty;
public Transform(float rotation, float tx, float ty) {
super(TRANSFORM);
this.rotation = rotation;
this.tx = tx;
this.ty = ty;
}
public float getRotation() {
return rotation;
}
public float getTx() {
return tx;
}
public float getTy() {
return ty;
}
}
}
我试图通过进一步扩展BaseEvents来允许创建新事件的能力。我主要使用静态内部类来组织。我不想为每个活动创建一个单独的课程。
事件处理程序
为了避免使用EventHandler类对给定处理器中的每个事件进行硬编码处理。我的计划是每个事件都有一个EventHandler类。我再次使用静态内部类进行组织。
这里是EventHandler抽象类:
public abstract class EventHandler {
public void handle(Event event, Component component) {
}
}
这里是BaseEventHandlers"工厂"类:
public class BaseEventHandlers extends EventHandler {
public static class Transform extends BaseEventHandlers {
@Override
public void handle(Event event, Component component) {
BaseEvents.Transform e = (BaseEvents.Transform) event;
RenderComponent c = (RenderComponent) component;
c.setRotation(e.getRotation());
c.setTx(e.getTx());
c.setTy(e.getTy());
}
}
}
示例代码I显示的是RenderComponent / RenderProcessor配对。我们关心转换事件,因为它们告诉我们重新绘制对象的位置。
当EventManager通知RenderProcessor一个新事件时,我们使用事件ID检查Map以获取相应的EventHandler,并调用其handle方法。注意,事件实际上存储在处理器队列中并在更新调用期间处理,如下所示:
...
protected final Map<Integer, EventHandler> eventHandlers = new HashMap<>();
...
@Override
public void update() {
events.stream()
.forEach(event -> {
eventHandlers.get(event.getEventID()).handle(event, components.get(event.getSourceEntityID()));
});
events.clear();
}
...
我的问题
在EventHandler中,我需要将Event和Component抽象类都转换为适当的具体类。我只限于一种类型的活动,但我不能将自己限制在一种类型的组件中。我想要的是使用多态和重载,以便我有类似的东西:
...
public void handle(Event event, RenderComponent component) {
BaseEvents.Transform e = (BaseEvents.Transform) event;
component.setRotation(e.getRotation());
component.setTx(e.getTx());
component.setTy(e.getTy());
}
public void handle(Event event, OtherComponent component) {
BaseEvents.Transform e = (BaseEvents.Transform) event;
component.setRotation(e.getRotation());
component.setTx(e.getTx());
component.setTy(e.getTy());
}
...
这不会起作用,因为我只能访问抽象类的句柄(事件事件,组件组件)方法(重载似乎并不关心子类)。一个想法是创建一个像Transformable这样的接口,让RenderComponent和OtherComponent实现它。当事件中包含的数据适用于两个组件时,这种方法很有效,但对于某些事件而言,情况很容易发生。
例如,假设我有一个关闭一个名为WindowClosed的窗口的事件。我需要播放声音,绘制关闭动画,并更新打开的窗口数量。这是三个不同的组件/处理器需要处理的一个事件。在这个例子中,唯一可以使用的接口是覆盖每个Component所需的所有方法的接口,在我看来,这会导致凌乱,杂乱的意大利面条代码。
是否有一种聪明的方法可以使用泛型来解决这个问题?