我正在重构我们的遗留应用程序的一部分,它处理从/到excel表的db表的导出和导入。我们有一个
Formatter
为每个表提供子类,以提供该表的定义:它有多少列,以及每列的名称、格式和验证器。然后由导出/导入表的模板方法调用提供此数据的getter。我已经将列数据提取到枚举中,这大大简化了代码。格式化程序现在如下所示(为简洁起见省略了一些细节):
public class DamageChargeFormatter extends BaseFormatter {
public static final int NUM_COLUMNS = 7;
public enum Column {
VEHICLE_GROUP(0, "Vehicle Group", /* more params */),
NAME_OF_PART(1, "Name of Part", /* more params */),
//...
LOSS_OF_USE(6, "Loss of Use", /* more params */);
private static final Map<Integer, Column> intToColumn = new HashMap<Integer, Column>();
static {
for (Column type : values()) {
intToColumn.put(type.getIndex(), type);
}
}
public static TableColumn valueOf(int index) {
return intToColumn.get(index);
}
private int index;
private String name;
Column(int index, String name, /* more params */) {
this.index = index;
this.name = name;
//...
}
public int getIndex() { return index; }
public String getName() { return name; }
// more members and getters...
}
protected String getSheetName() {
return "Damage Charges";
}
public String getColumnName(int columnNumber) {
TableColumn column = Column.valueOf(columnNumber);
if (column != null) {
return column.getName();
}
return null;
}
// more getters...
protected int getNumColumns() {
return NUM_COLUMNS;
}
protected boolean isVariableColumnCount() {
return false;
}
}
现在,我有十几个这样的类,每个类都包含完全相同的代码,除了
NUM_COLUMNS
以及
Column
是不同的。有什么方法可以把它概括成这样吗?主要的障碍是静电
Column.valueOf()
方法与静态常数
数字列
. 后者的另一个关注点是,它实际上属于一个更高层次的抽象,即表,而不是单个列——以某种方式将其合并到通用解决方案中会更好。
从技术上讲,我可以用一个基本接口来解决这个问题(
TableColumn
下面)和反射,但我不太喜欢,因为除了将编译时错误转换为运行时错误之外,它还使代码难看(对我来说):
public class GenericFormatter<E extends TableColumn> extends BaseFormatter {
private Method valueOfMethod;
public GenericFormatter(Class<E> columnClass) {
try {
valueOfMethod = columnClass.getDeclaredMethod("valueOf", Integer.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public String getColumnName(int columnNumber) {
try {
@SuppressWarnings("unchecked")
E elem = (E) valueOfMethod.invoke(columnNumber);
if (elem != null) {
return elem.getName();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
//...
}
请注意,这段代码是纯实验性的,尚未测试…
有没有更好,更干净,更安全的方法?