Javagenerics – 太复杂了? 如何简化?

最初我在CodeReview上发布了这个问题,但这更适合StackOverflow。

我正在编写一个使用Java 6的多步骤过程。假设有3个步骤。
每个都接受相同类型的输入。 让我们开始。

这是作为输入传递给每个步骤的对象。 此对象充当另一类对象的包装器,以及一些步骤的共享值。 请注意,名称会被翻译为更通用的域名,而使用英语,原件是意大利语。

public class EntityStepInput { public final T entity; public boolean modified; public boolean canceled; public EntityStepInput(final T entity) { this.entity = entity; } } 

这是每个步骤使用的接口。

 public interface EntityStep<T extends EntityStepInput> { void process(final T stepInput) throws Exception; } 

现在,3个步骤中的2个必须接受包含Entity或从中派生的任何类型的EntityStepInput

 public class FirstEntityStep implements EntityStep<EntityStepInput> { @Override public void process(final EntityStepInput stepInput) throws Exception {} } public class SecondEntityStep implements EntityStep<EntityStepInput> { @Override public void process(final EntityStepInput stepInput) throws Exception {} } 

最后一步必须接受EntityStepInput ,其中包含从Entity派生的特定类型。

 public class ThirdEntityStep implements EntityStep<EntityStepInput> { @Override public void process(final EntityStepInput stepInput) throws Exception {} } 

用法非常简单。 我有重载方法,接受不同类型的Entity 。 以下是简化版本。

 public void workWithEntity(final DerivedEntity entity) throws Exception { final EntityStepInput stepInput = new EntityStepInput(entity); stepOne.process(stepInput); stepTwo.process(stepInput); stepThree.process(stepInput); } 

如您所见, DerivedEntity类型能够使用所有步骤。

 public void workWithEntity(final OtherDerivedEntity entity) throws Exception { final EntityStepInput stepInput = new EntityStepInput(entity); stepOne.process(stepInput); stepTwo.process(stepInput); } 

在这里,另一种类型的Entity不能使用最后一步,这就是我想要的。

现在,这与generics变得相当复杂。 我担心在我离开之后谁会阅读我的代码将不会理解,迟早会发生混乱。

这可以简化吗? 您的方法将尽可能多地尊重单一责任原则?

编辑。 Entity层次结构如下:

 Entity > DerivedEntity Entity > OtherDerivedEntity 

一个较小的更改只是将EntityStep上的类型变量声明简化为Entity而不是EntityStepInput

 interface EntityStep { void process(EntityStepInput i); } 

然后:

 class FirstEntityStep implements EntityStep { @Override public void process(EntityStepInput i) {} } class SecondEntityStep implements EntityStep { @Override public void process(EntityStepInput i) {} } class ThirdEntityStep implements EntityStep { @Override public void process(EntityStepInput i) {} } 

它和以前完全一样,但声明更容易理解。

如果你想使用某个特定的子类,你只需要T extends EntityStepInput<...> ,但由于你总是直接使用EntityStepInput ,所以你不需要它。

这是我第二次尝试回答。 我认为你目前使用的系统看起来不错; 它提供了编译时检查,因为您不希望允许步骤#3尝试处理任何不是DerivedEntity (或其子项之一)的类型。

您可以使用List>来简化此操作List> List> ,但是你失去了第3步的编译时类型检查,并被迫通过使用instanceof改进它:

Java 8+解决方案:

 List> processes = new ArrayList<>(); processes.add(entity -> { // Process first step. }); processes.add(entity -> { // Process second step. }); processes.add(entity -> { if (!(entity instanceof DerivedEntity)) { System.out.println("Step 3: The entity must be a DerivedEntity!"); return; } // Process third step. }); 

要通过管道传递Entity ,它就像:

 processes.forEach(consumer -> consumer.accept(entity)); 

Java 6+解决方案(让我们创建自己的Consumer界面!):

 public interface Consumer { void accept(T t); } 

与上面相同的代码,但使用我们的Consumer接口:

 List> processes = new ArrayList>(); processes.add(new Consumer() { @Override public void accept(Entity entity) { // Process first step. } }); processes.add(new Consumer() { @Override public void accept(Entity entity) { // Process second step. } }); processes.add(new Consumer() { @Override public void accept(Entity entity) { if (!(entity instanceof DerivedEntity)) { System.out.println("Step 3: The entity must be a DerivedEntity!"); return; } // Process third step. } }); Entity entity = new DerivedEntity(); for (Consumer consumer : processes) { consumer.accept(entity); }