根据枚举参数选择Spring bean

问题描述 投票:2回答:2

在我的Spring Boot应用程序中,我有一个StageStageProcessor的概念来处理StageStage有一个StageType enum财产。我有不同的StageProcessor接口实现,这些实现是Spring bean。现在,我有另一个Spring bean,WorkflowProcessor,需要根据StageProcessorStageType调用合适的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机制。有更好设计的想法吗?

java spring spring-boot design-patterns
2个回答
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);
    }
}

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.

© www.soinside.com 2019 - 2024. All rights reserved.