我的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 = ...
}
}
我知道枚举是自然有序的(有序的),因此,通过以正确的顺序声明它们,就不需要进行任何排序。但是,枚举值的数量很大,可能会随着时间的推移而变化。我不想自己承担维护正确顺序的负担,如果我只是声明依赖项,我希望程序能帮我做到这一点。它也是自我解释的代码,因为它明确地提到了cetain依赖项的存在,并且它们是经过排序的。
我的程序的目标是以正确的顺序在一组记录上运行计算器,因此为什么要对枚举进行排序:
for(Record r : records)
{
for(DataType type : DataType.DATA_TYPES_SORTED_BY_DEPENDENCIES)
{
Integer result = type.getCalculator().calculate(r);
r.getDataMap().put(type, result);
}
}
这个设置一直正常运行,直到有一个需求出现,即计算器(过去在enum类中静态实例化)应该是可参数化的。参数将来自webservice或数据库调用。我得恢复正常生活
计算器
类,我现在已经失去了枚举类型和计算器之间的链接。
为了解决这个问题,我创建了一个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;
这让我很困扰,因为我在概念上声明了两次(相当大的)枚举:一次用于排序逻辑,一次用于与计算器的链接。有没有办法防止这种情况发生?