将Java Enum值链接到动态实例化的对象

时间:2019-06-28 00:24:50

标签: java enums

我的Java 8应用程序中有一个代码异味,我希望通过重新设计来解决。

我已经声明了一个枚举DataType,它不仅包含枚举值,而且还包含基于某些逻辑的这些枚举值的有序列表。总而言之,每个枚举值声明一组与其他枚举值(相同类型)的依赖关系,并且列表是这些枚举值的topologically sorted list。每个枚举值还具有一个与之关联的Calculator

public Enum DataType
{
    A(EnumSet.noneOf(DataType.class), new CalculatorA()),
    B(EnumSet.of(A), new CalculatorB()),
    C(EnumSet.noneOf(DataType.class), new CalculatorC()),
    D(EnumSet.Of(A,B,C), new CalculatorD()),
    ... more ...

    ...constructor and attributes...

    public static final List<DataType> DATA_TYPES_SORTED_BY_DEPENDENCIES;

    static
    {
        DATA_TYPES_SORTED_BY_DEPENDENCIES = ...
    }
}

我知道枚举是自然排序的(普通的),因此通过以正确的顺序声明枚举,就无需进行任何排序。但是,枚举值的数量很大,并且会随时间变化。我不想自己维护正确的顺序,如果我只是声明依赖项,我希望程序为我自己做。它也是自解释代码,因为它明确提到了某些依赖项存在并且已对其进行排序。

我的程序的目标是以正确的顺序在一组记录上运行计算器,因此为什么要对枚举进行排序:

for(Record r : records)
{
    for(DataType type : DataType.DATA_TYPES_SORTED_BY_DEPENDENCIES)
    {
        Integer result = type.getCalculator().calculate(r);
        r.getDataMap().put(type, result);
    }
} 

此设置运行正常,直到需要对可在枚举类中静态实例化的计算器进行参数化为止。参数将来自Web服务或数据库调用。我不得不在枚举之外实例化Calculator类,现在我已经失去了枚举类型和计算器之间的联系。

为了解决这个问题,我创建了一个HashMap以便于检索:

    ...get some parameters from another service...

    Map<DataType, Calculator> calculatorsByTypeMap = new HashMap<>(400);

    calculatorsByTypeMap.put(DataType.A, new CalculatorA(someParameterA));
    calculatorsByTypeMap.put(DataType.B, new CalculatorB());
    calculatorsByTypeMap.put(DataType.C, new CalculatorC(someParameterC1, somereParameterC2));
    calculatorsByTypeMap.put(DataType.D, new CalculatorD(someParameterD));
    ...

    return calculatorsByTypeMap;

这让我感到困扰,因为我在概念上两次声明了我的(相当大的)枚举:一次用于排序逻辑,一次用于与计算器的链接。有办法防止这种情况吗?

1 个答案:

答案 0 :(得分:0)

使用空计算器字段构建枚举。在运行时,进行拓扑排序并构建排序列表。获取新的计算器并在枚举中设置计算器值。