最初我在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;
}
}
这是每个步骤使用的界面。
public interface EntityStep<T extends EntityStepInput<? extends Entity>> {
void process(final T stepInput) throws Exception;
}
现在,三个步骤中的两个必须接受一个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
答案 0 :(得分:2)
这是我第二次尝试回答。我认为您当前使用的系统看起来不错;它提供了编译时检查,因为您不想让步骤3尝试处理不是DerivedEntity
(或其子元素之一)的任何类型。
您可以使用List<Consumer<? extends Entity>>
简化此操作,但是您会丢失对步骤#3的编译时类型检查,而不得不使用instanceof
来改善它:
Java 8+解决方案:
List<Consumer<Entity>> 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<T> {
void accept(T t);
}
与上面相同的代码,但是使用我们的Consumer
界面:
List<Consumer<Entity>> processes = new ArrayList<Consumer<Entity>>();
processes.add(new Consumer<Entity>() {
@Override
public void accept(Entity entity) {
// Process first step.
}
});
processes.add(new Consumer<Entity>() {
@Override
public void accept(Entity entity) {
// Process second step.
}
});
processes.add(new Consumer<Entity>() {
@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<Entity> consumer : processes) {
consumer.accept(entity);
}
答案 1 :(得分:1)
一个较小的更改只是将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
,因此不需要。