英文:
Design Issue with Event/Action mechanism, Java generics
问题
我遇到了一个与我的当前事件/动作机制设计相关的问题。有许多事件,可以通过特定的标准来区分。这导致了一个类层次结构。
public interface Event
,public abstract class EventCategory implements Event
和一个实际的事件,例如 public class ActualEvent extends EventCategory
。然后有一些能够根据给定的事件执行操作的动作。
public interface Action<T extends Event> {
void execute(T event);
}
以及一个实际的动作 ActualAction<T extends EventCategory> implements Action<T>
。
现在有工厂来生成具体的实例。
public interface ActionFactory<T extends Event> {
Action<T> create(String actionData);
}
public class ActualActionFactory implements ActionFactory<EventCategory> {
@Override
Action<T> create(String actionData);
}
最后,有事件消费者,每个事件消费者都有一个动作,并将处理事件的发生,并执行构建的动作。
public interface EventConsumer<T extends Event> {
void handleEvent(T event);
}
public interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String data, Action<T> action);
}
编排器类,它保存所有的 ActionFactory 并委派 create 调用。
public class Orchestrator {
private final List<ActionFactory<? extends Event>> factories = Lists.newArrayList();
private final List<EventConsumerFactories<? extends Event>> consumerFactories = Lists.newArrayList();
public void createAction(String actionData) {
for (ActionFactory<? extends Event> factory : factories) {
Action<? extends Event> action = factory.create(actionData);
if (action != null) {
consumerFactories.forEach(cf -> cf.create(null, action));
}
}
我在最后一部分遇到了问题。如果将动作类型定义为 Action<? extends Event>
,则 consumerFactories 的 create 调用会报错 "Required <capture of ? extends Event>, provided <capture of ? extends Event>"。
我的类层次结构或模板边界有什么问题吗?如果在这个地方使用原始类型,一切都能正常工作,配置的事件可以执行。但是我想摆脱原始类型。
谢谢你的帮助!
亲切的问候,
Andreas
编辑:添加注册工厂的代码
public interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String consumerData, Action<? super Event> action);
}
public class ActualEventConsumerFactory implements EventConsumerFactory<ActualEvent> {
}
编排器注册
void registerConsumerFactory(ConsumerFactory<? super Event> factory) {
this.consumerFactories.add(factory);
}
英文:
I'm facing a problem with my current design for an Event/Action mechanism. There are numerous Events, that can be distinguished by certain criteria. This results in a class hierarchy.
public interface Event
, public abstract class EventCategory implements Event
and an actual event e.g. public class ActualEvent extends EventCategory
. Then there are Actions which are able to perform operations based on the Event given.
public interface Action<T extends Event> {
void execute(T event);
}
and an actual Action ActualAction<T extends EventCategory> implements Action<T>
.
Now there are Factories that generate the specific instances,
public interface ActionFactory<T extends Event> {
Action<T> create(String actionData);
}
public class ActualActionFactory implements ActionFactory<EventCategory> {
@Override
Action<T> create(String actionData);
}
Finally there are EventConsumers, each has one action and will handle the occurence of events and will execute the constructed action.
public interface EventConsumer<T extends Event> {
void handleEvent(T event);
}
public interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String data, Action<T> action);
}
The orchestrator class, which holds all ActionFactories and delegates the create Calls
public class Orchestrator {
private final List<ActionFactory<? extends Event>> factories = Lists.newArrayList();
private final List<EventConsumerFactories<? extends Event>> consumerFactories = Lists.newArrayList();
public void createAction(String actionData) {
for (ActionFactory<? extends Event> factory : factories) {
Action<? extends Event> action = factory.create(actionData);
if (action != null) {
consumerFactories.forEach(cf -> cf.create(null, action));
}
}
Im struggling with the last part. If type the Action as above, Action<? extends Event>
the create call for consumerFactories complains "Required <capture of ? extends Event>, provided <capture of ? extends Event>".
What is the problem with my class hierarchy or template bounds? If use raw types for the action at this place everything works and the actions execute for the configured events. But i would like to get rid of the raw types.
Thanks for your help!
Kind Regards,
Andreas
Edit: adding code how factories are registered
public interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String consumerData, Action<? super Event> action);
}
public class ActualEventConsumerFactory implements EventConsumerFactory<ActualEvent> {
}
Orchestrator Registration
void registerConsumerFactory(ConsumerFactory<? super Event> factory) {
this.consumerFactories.add(factory);
}
答案1
得分: 1
问题的根本在于您使用了错误的边界类型。
EventConsumer
和 Action
都接受T
的实例:它们是消费者。因此,您不应该使用extends
边界来声明它们,因为您将无法将任何东西传递给它们(除了文字上的null
)。
如果您将这些边界更改为super
,则您的代码将编译通过:
interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String data, Action<? super T> action);
}
class Orchestrator {
private final List<ActionFactory<? super Event>> factories = Lists.newArrayList();
private final List<EventConsumerFactory<? super Event>> consumerFactories = Lists.newArrayList();
public void createAction(String actionData) {
for (ActionFactory<? super Event> factory : factories) {
Action<? super Event> action = factory.create(actionData);
if (action != null) {
consumerFactories.forEach(cf -> cf.create(null, action));
}
}
}
}
请注意,我已将代码中需要更改的部分标记为了"here"。
英文:
The fundamental issue here is that you're using the wrong bound type.
Both EventConsumer
and Action
accept instances of T
: they're consumers. As such, you don't want to be declaring them with extends
bounds, because you won't be able to pass anything to them (other than literal null
).
You code compiles if you change these bounds to super
:
interface EventConsumerFactory<T extends Event> {
EventConsumer<T> create(String data, Action<? super T> action);
// here
}
class Orchestrator {
private final List<ActionFactory<? super Event>> factories = Lists.newArrayList();
// here
private final List<EventConsumerFactory<? super Event>> consumerFactories = Lists.newArrayList();
// here
public void createAction(String actionData) {
for (ActionFactory<? super Event> factory : factories) {
// here
Action<? super Event> action = factory.create(actionData);
// here
if (action != null) {
consumerFactories.forEach(cf -> cf.create(null, action));
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论