如何简化Java Swing单位转换器中基于枚举类别设置JComboBox模型的冗长if-else链?
如何简化Java Swing单位转换器中基于枚举类别设置JComboBox模型的冗长if-else链?
我完全懂这种重复代码的痛苦——一堆if-else不仅看着闹心,以后加新类别还得改半天,维护起来太麻烦了。给你几个实用的重构思路,一步步把代码变清爽:
思路一:用映射表(Map)关联类别与枚举数组
这是改动最小、见效最快的方案,核心是把「类别字符串」和「对应的枚举数组」提前存到一个Map里,彻底替代一堆条件判断:
步骤1:定义并初始化映射表
在你的类中添加一个静态Map,用静态代码块完成初始化,把所有类别和对应的枚举值关联起来:
import java.util.HashMap; import java.util.Map; // 在类内部定义静态映射表 private static final Map<String, Object[]> CATEGORY_TO_UNITS = new HashMap<>(); // 静态代码块初始化映射关系 static { CATEGORY_TO_UNITS.put("LENGTH", Length.values()); CATEGORY_TO_UNITS.put("WEIGHT", Weight.values()); CATEGORY_TO_UNITS.put("TEMPERATURE", Temperature.values()); CATEGORY_TO_UNITS.put("TIME", Time.values()); CATEGORY_TO_UNITS.put("VOLUME", Volume.values()); CATEGORY_TO_UNITS.put("AREA", Area.values()); CATEGORY_TO_UNITS.put("SPEED", Speed.values()); CATEGORY_TO_UNITS.put("ENERGY", Energy.values()); }
步骤2:重构selectUnit方法
原来的一堆if-else直接替换成Map查找,代码瞬间简洁:
private void selectUnit(ActionEvent e) { // 获取选中的类别字符串 String selectedCategory = view.getCategoryBox().getSelectedItem().toString(); // 从映射表中取出对应的枚举数组 Object[] units = CATEGORY_TO_UNITS.get(selectedCategory); if (units != null) { // 统一设置两个ComboBox的模型 view.getInputBoxUnit().setModel(new DefaultComboBoxModel<>(units)); view.getOutputBoxUnit().setModel(new DefaultComboBoxModel<>(units)); } // 可选:如果需要处理未匹配的类别,这里可以加日志或默认逻辑 }
优势:以后新增单位类别,只需要在静态代码块里加一行put即可,完全不用修改业务逻辑代码,完美符合「开闭原则」。
思路二:把类别也封装成枚举(更健壮的方案)
如果想彻底消除字符串硬编码的风险(比如拼写错误导致的bug),可以把类别本身也定义成枚举,让编译期帮我们检查错误:
步骤1:定义Category枚举
把每个类别和对应的单位枚举数组绑定在一起:
enum Category { LENGTH(Length.values()), WEIGHT(Weight.values()), TEMPERATURE(Temperature.values()), TIME(Time.values()), VOLUME(Volume.values()), AREA(Area.values()), SPEED(Speed.values()), ENERGY(Energy.values()); private final Object[] units; // 构造方法关联单位枚举数组 Category(Object[] units) { this.units = units; } // 提供获取单位数组的方法 public Object[] getUnits() { return units; } }
步骤2:更新CategoryBox的模型
初始化JComboBox时,直接用Category枚举作为选项,不用再用字符串:
// 替换原来的字符串选项,改用Category枚举 view.getCategoryBox().setModel(new DefaultComboBoxModel<>(Category.values()));
步骤3:重构selectUnit方法
现在选中的直接是Category对象,无需字符串转换,代码更简洁安全:
private void selectUnit(ActionEvent e) { Category selectedCategory = (Category) view.getCategoryBox().getSelectedItem(); if (selectedCategory != null) { Object[] units = selectedCategory.getUnits(); view.getInputBoxUnit().setModel(new DefaultComboBoxModel<>(units)); view.getOutputBoxUnit().setModel(new DefaultComboBoxModel<>(units)); } }
优势:彻底避免了字符串硬编码的潜在bug,比如如果不小心把"LENGTH"写成"LENGHT",编译期直接报错,而不是运行时才出问题,长期维护更可靠。
额外小提示
如果你的所有单位枚举(Length、Weight等)都实现了同一个通用接口(比如Unit),可以把Map的泛型从Object[]改成Unit[],进一步提升类型安全性,避免不必要的类型转换。
内容来源于stack exchange
相关产品推荐
相关产品推荐

