我的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;
这让我感到困扰,因为我在概念上两次声明了我的(相当大的)枚举:一次用于排序逻辑,一次用于与计算器的链接。有办法防止这种情况吗?
答案 0 :(得分:0)
使用空计算器字段构建枚举。在运行时,进行拓扑排序并构建排序列表。获取新的计算器并在枚举中设置计算器值。