根据枚举参数选择Spring bean

时间:2019-03-05 16:44:20

标签: java spring spring-boot design-patterns

在我的Spring Boot应用程序中,我有一个StageStageProcessor的概念,该概念处理StageStage具有一个StageType枚举属性。我有StageProcessor接口的不同实现,这些实现是Spring Bean。现在,我还有另一个Spring bean WorkflowProcessor,它需要根据StageProcessor中的StageType来调用适当的Stage。到目前为止,我已经提出了以下建议:

@Service
public class StageConfig {
    @Autowired
    private StageProcessorA stageProcessorA;
    @Autowired
    private StageProcessorB stageProcessorB;

    public StageProcessor getProcessor(Stage stage) {
        switch(stage.getType()) {
            case A:
                return stageProcessorA;
                break;
            case B:
                return stageProcessorB;
                break;
        }
    }
}

我想知道我是否缺少任何设计模式或Spring机制。有更好的设计想法吗?

2 个答案:

答案 0 :(得分:1)

这取决于您案件的具体情况。在许多情况下,阶段实际上不是像枚举中那样硬编码的,而是可以为各种系统配置的。此外,您拥有的潜在阶段越多,设置稍微冗长但避免重复的收益就越大。

通常,我会在这里推荐Spring的解析器模式。代码看起来像这样,其中KeyType通常是一个枚举或字符串。一般的想法是,每个实现都会告诉您它可以处理的各种事物(阶段,类型,参数等),然后您查找匹配项。 (没有直接映射查找的一种变体是使用boolean canHandle(something)并进行迭代,直到找到一个为止。)

interface StageProcessor {
    OutputType process(Stage stage);
    KeyType stageKey();
}

@Service
class StageProcessors {
    Map<KeyType, StageProcessor> stageProcessors;

    StageProcessors(Collection<StageProcessor> processors) {
        stageProcessors = processors.stream().collect(groupingBy(StageProcessor::stageKey));
        assert stageProcessors.size() == expectedNumberOfProcessors;
    }

    StageProcessor getProcessor(KeyType stage) {
        // although usually your service would take care of dispatching directly
        return stageProcessors.get(stage);
    }
}

(并注意:Avoid field injection.

答案 1 :(得分:0)

这完全基于@chrylis的想法,只是处理器不需要为此更改其API,您可以使用注释进行操作。另外,在一种情况下,可能会有多个处理器。

interface StageProcessor {
    OutputType process(Stage stage);
}

@Component
@Processes(StageType.A)
class StageProcessorA implements StageProcessor{
      OutputType process(Stage stage){
        //validate stage is StageType.A
      }
}

@interface Processes{
    StageType type;
    StageType getType(){
        return type;
    }
}

@Component
@Processes(StageType.B)
class StageProcessorB implements StageProcessor{

}

@Service
class StageProcessors {
    Map<StageType, List<StageProcessor>> stageProcessors;

    StageProcessors(Collection<StageProcessor> processors) {
        Map<StageType, List<StageProcessor>> map = new HashMap<>();
        for (StageProcessor processor : processors) {
            StageType stageType = processor.getClass().getAnnotation(Processes.class).getType();
            map.computeIfAbsent(stageType, k -> new ArrayList<>()).add(processor);
        }
        stageProcessors = map;
        assert stageProcessors.size() == expectedNumberOfProcessors;
    }

    List<StageProcessor> getProcessors(StageType stage) {
        return stageProcessors.get(stage);
    }
}