设计问题与事件/动作机制,Java泛型

huangapple go评论67阅读模式
英文:

Design Issue with Event/Action mechanism, Java generics

问题

我遇到了一个与我的当前事件/动作机制设计相关的问题。有许多事件,可以通过特定的标准来区分。这导致了一个类层次结构。

public interface Eventpublic 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&lt;T extends Event&gt; {
  void execute(T event);
}

and an actual Action ActualAction&lt;T extends EventCategory&gt; implements Action&lt;T&gt; .
Now there are Factories that generate the specific instances,

public interface ActionFactory&lt;T extends Event&gt; {
  Action&lt;T&gt; create(String actionData);
}

public class ActualActionFactory implements ActionFactory&lt;EventCategory&gt; {
  @Override 
  Action&lt;T&gt; 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&lt;T extends Event&gt; {
  void handleEvent(T event);
}

public interface EventConsumerFactory&lt;T extends Event&gt; {
  EventConsumer&lt;T&gt; create(String data, Action&lt;T&gt; action);
}

The orchestrator class, which holds all ActionFactories and delegates the create Calls

public class Orchestrator {
 private final List&lt;ActionFactory&lt;? extends Event&gt;&gt; factories = Lists.newArrayList();
 private final List&lt;EventConsumerFactories&lt;? extends Event&gt;&gt; consumerFactories = Lists.newArrayList();
 
 public void createAction(String actionData) {
   for (ActionFactory&lt;? extends Event&gt; factory : factories) {
     Action&lt;? extends Event&gt; action = factory.create(actionData);
     if (action != null) {
       consumerFactories.forEach(cf -&gt; cf.create(null, action));
     }
 }

Im struggling with the last part. If type the Action as above, Action&lt;? extends Event&gt; 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&lt;T extends Event&gt; {
  EventConsumer&lt;T&gt; create(String consumerData, Action&lt;? super Event&gt; action);
}
public class ActualEventConsumerFactory implements EventConsumerFactory&lt;ActualEvent&gt;  {
}

Orchestrator Registration

  void registerConsumerFactory(ConsumerFactory&lt;? super Event&gt; factory) {
    this.consumerFactories.add(factory);
   }

答案1

得分: 1

问题的根本在于您使用了错误的边界类型。

EventConsumerAction接受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&lt;T extends Event&gt; {
  EventConsumer&lt;T&gt; create(String data, Action&lt;? super T&gt; action);
                                             // here
}

class Orchestrator {
  private final List&lt;ActionFactory&lt;? super Event&gt;&gt; factories = Lists.newArrayList();
                                  // here
  private final List&lt;EventConsumerFactory&lt;? super Event&gt;&gt; consumerFactories = Lists.newArrayList();
                                         // here

  public void createAction(String actionData) {
    for (ActionFactory&lt;? super Event&gt; factory : factories) {
                      // here
      Action&lt;? super Event&gt; action = factory.create(actionData);
            // here
      if (action != null) {
        consumerFactories.forEach(cf -&gt; cf.create(null, action));
      }
    }
  }
}

huangapple
  • 本文由 发表于 2020年8月7日 19:04:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63300503.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定