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

我正在使用Java 6为多步骤过程进行编码。假设其中有3个步骤。
每个接受相同类型的输入。
让我们开始。

这是作为输入传递到每个步骤的对象。除了某些步骤的共享值外,该对象还用作另一种对象的包装。
请注意,姓名已翻译成更通用的域名,并且英文使用的是英文原文。

public class EntityStepInput<T extends Entity> {
    public final T entity;
    public boolean modified;
    public boolean canceled;

    public EntityStepInput(final T entity) {
        this.entity = entity;
    }
}

这是每个步骤使用的接口(interface)。
public interface EntityStep<T extends EntityStepInput<? extends Entity>> {
    void process(final T stepInput) throws Exception;
}

现在,这3个步骤中的2个必须接受一个EntityStepInput,其中包含一个Entity或从其派生的任何类型。
public class FirstEntityStep implements EntityStep<EntityStepInput<? extends Entity>> {
    @Override
    public void process(final EntityStepInput<? extends Entity> stepInput) throws Exception {}
}

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

最后一步必须接受EntityStepInput,其中包含从Entity派生的特定类型。
public class ThirdEntityStep implements EntityStep<EntityStepInput<? extends DerivedEntity>> {
    @Override
    public void process(final EntityStepInput<? extends DerivedEntity> stepInput) throws Exception {}
}

用法很简单。我有重载的方法,它们接受不同类型的Entity。接下来是一个简化的版本。
public void workWithEntity(final DerivedEntity entity) throws Exception {
    final EntityStepInput<DerivedEntity> stepInput = new EntityStepInput<DerivedEntity>(entity);

    stepOne.process(stepInput);
    stepTwo.process(stepInput);
    stepThree.process(stepInput);
}

如您所见,DerivedEntity类型能够使用所有步骤。
public void workWithEntity(final OtherDerivedEntity entity) throws Exception {
    final EntityStepInput<OtherDerivedEntity> stepInput = new EntityStepInput<OtherDerivedEntity>(entity);

    stepOne.process(stepInput);
    stepTwo.process(stepInput);
}

在这里,另一种Entity无法使用最后一步,这就是我想要的。

现在,使用泛型变得相当复杂。我担心谁会在我走后阅读我的代码,这将不明白,迟早会造成困惑。

这是可简化的吗?在遵循单一责任原则的前提下,您想采取什么方式来尊重他人?

编辑。 Entity层次结构如下:
Entity > DerivedEntity
Entity > OtherDerivedEntity

最佳答案

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

interface EntityStep<E extends Entity> {
    void process(EntityStepInput<? extends E> i);
}

然后:
class FirstEntityStep implements EntityStep<Entity> {
    @Override
    public void process(EntityStepInput<? extends Entity> i) {}
}
class SecondEntityStep implements EntityStep<Entity> {
    @Override
    public void process(EntityStepInput<? extends Entity> i) {}
}
class ThirdEntityStep implements EntityStep<DerivedEntity> {
    @Override
    public void process(EntityStepInput<? extends DerivedEntity> i) {}
}

它与以前完全相同,但是声明更容易理解。

如果要使用某些特定的子类,则只需要T extends EntityStepInput<...>,但是由于您始终直接使用EntityStepInput,因此不需要它。

10-06 08:59