简体   繁体   English

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

[英]Link Java Enum values to dynamically instantiated objects

I've got a code smell in my Java 8 application which I would like to resolve by some redesign. 我的Java 8应用程序中有一个代码异味,我希望通过重新设计来解决。

I have declared an Enum DataType which contains not just enum values, but also an ordered list of these enum values based on some logic. 我声明了一个Enum DataType ,它不仅包含枚举值,而且还基于某些逻辑包含这些枚举值的有序列表。 To summarize, every enum value declares a set of dependencies on other enum values (of the same type) and the list is a topologically sorted list of these enum values. 总而言之,每个枚举值声明一组与其他枚举值(相同类型)的依赖性,并且该列表是这些枚举值的拓扑排序列表 Every enum value also has a Calculator associated with it. 每个枚举值还具有与之关联的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 = ...
    }
}

I know enums are naturally ordered (ordinal) and thus by declaring them in the correct order there would no need to do any kind of sorting. 我知道枚举是自然排序的(常规的),因此通过以正确的顺序声明枚举,就无需进行任何排序。 However, the amount of enum values is large and can change over time. 但是,枚举值的数量很大,并且会随时间变化。 I don't want to be burdened with maintaining the correct order myself, I want the program to do it for me if I just declare the dependencies. 我不想自己维护正确的顺序,如果我只是声明依赖项,我希望程序为我自己做。 It is also self explaining code, because it is expliticly mentioned that cetain dependencies exist and that they are sorted. 它也是自我解释的代码,因为明确提到了某些依赖项存在并且已对其进行排序。

The goal of my program is to run the calculators on a set of records in the correct order, hence why the enum is ordered: 我的程序的目标是以正确的顺序在一组记录上运行计算器,因此为什么要对枚举进行排序:

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

This setup was running ok until a requirement came that the calculators, which used to be statically instantiated within the enum class, should be parameterizable. 此设置运行正常,直到要求对可在参数枚举类中静态实例化的计算器进行参数化。 The parameters will come from a webservice or database call. 参数将来自Web服务或数据库调用。 I have to instatiate the Calculator classes outside of the enum, and I have now lost the link between enum types and calculators. 我必须在枚举之外实例化Calculator类,而现在我已经失去了枚举类型和计算器之间的联系。

To remedy that, I created a HashMap for easy retrieval: 为了解决这个问题,我创建了一个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;

This bothers me because I have conceptually declared my (rather large) enum twice: once for the ordering logic, and once for the linking with the calculators. 这让我感到困扰,因为我在概念上两次声明了我的(相当大的)枚举:一次用于排序逻辑,一次用于与计算器的链接。 Is there a way to prevent this? 有办法防止这种情况吗?

Build the enum with a null calculator field. 使用空计算器字段构建枚举。 At runtime, do a topological sort and build the sorted list. 在运行时,进行拓扑排序并构建排序列表。 Get the new calculators and set the calculator value in the enum. 获取新的计算器并在枚举中设置计算器值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM