Java工厂模式下消除if-else/switch实现多错误码校验的优化方案
解决方案
完全可以通过Map预映射的方案消除所有if-else分支,全程不需要反射,同时能完美解决方法长度过长、圈复杂度超标的问题,实现逻辑如下:
核心思路
把错误码和对应校验逻辑的实例/构造器提前存在Map容器中,获取校验实现时直接用传入的错误码作为key从Map中查询即可,查询复杂度为O(1),性能比if-else串行判断更高。
实现代码
场景1:校验类无状态(推荐,单例复用性能更高)
如果你的校验实现类没有成员变量,是无状态的,直接预存单例实例到Map即可:
// 先优化下接口命名,符合Java大驼峰规范 public interface ValidateErrCd { void check_errcd(); } // 校验实现类保持原有逻辑不变,仅调整类名首字母大写符合规范即可 public class ValidateErrCd_01 implements ValidateErrCd { @Override public void check_errcd() { // 原有业务逻辑不变 } } // 其他99个校验实现类同理不需要修改 // 改造后的工厂类 public class ErrorValidationFactory { // 存储错误码和校验实例的映射,key统一转小写实现忽略大小写匹配 private static final Map<String, ValidateErrCd> VALIDATOR_MAP; // 静态块初始化所有校验实现 static { VALIDATOR_MAP = new HashMap<>(); VALIDATOR_MAP.put("errcd_01", new ValidateErrCd_01()); VALIDATOR_MAP.put("errcd_02", new ValidateErrCd_02()); // 依次添加剩下的98个校验实现 VALIDATOR_MAP.put("errcd_100", new ValidateErrCd_100()); } public ValidateErrCd getValidation(String errorCode){ if (errorCode == null) { return null; } // 输入转小写后直接查询Map return VALIDATOR_MAP.get(errorCode.toLowerCase()); } }
场景2:校验类有状态,每次需要生成新实例
如果校验实现类存在成员变量,不能复用单例,可以把Map的value换成构造器引用,每次调用生成新实例:
public class ErrorValidationFactory { private static final Map<String, Supplier<ValidateErrCd>> VALIDATOR_SUPPLIER_MAP; static { VALIDATOR_SUPPLIER_MAP = new HashMap<>(); VALIDATOR_SUPPLIER_MAP.put("errcd_01", ValidateErrCd_01::new); VALIDATOR_SUPPLIER_MAP.put("errcd_02", ValidateErrCd_02::new); // 依次添加剩下的98个实现 VALIDATOR_SUPPLIER_MAP.put("errcd_100", ValidateErrCd_100::new); } public ValidateErrCd getValidation(String errorCode){ if (errorCode == null) { return null; } Supplier<ValidateErrCd> supplier = VALIDATOR_SUPPLIER_MAP.get(errorCode.toLowerCase()); return supplier != null ? supplier.get() : null; } }
拓展优化(Spring环境可选)
如果项目使用Spring框架,还可以进一步简化维护成本:
- 给每个校验实现类加
@Component注解,指定bean名称为对应的错误码 - 工厂类注入
ApplicationContext,直接通过applicationContext.getBean(errorCode.toLowerCase(), ValidateErrCd.class)获取对应实现 - 新增校验类时不需要修改工厂类代码,自动注册到Spring上下文即可
改造后工厂类的圈复杂度为1,方法长度仅不到10行,完全符合CheckStyle、PMD的规则要求,原有调用逻辑不需要做任何修改。
内容的提问来源于stack exchange,提问作者Data_Geek
相关产品推荐
相关产品推荐

