如何移除条件语句并优化员工验证引擎的现有设计?
优化验证引擎设计的方案
当然可以优化这个设计!现在客户端里的if/switch判断会随着员工类型的增加变得越来越臃肿,而且违反了开闭原则——每次新增员工类型都得修改客户端代码。下面给你几个实用的改进方案:
方案1:用工厂模式封装验证器创建逻辑
把创建验证器的逻辑抽离到专门的工厂类中,客户端只需要传入员工类型,不用关心具体实现类的细节:
public class EmployeeValidatorFactory { // 提前初始化所有验证器的映射 private static final Map<StaffType, EmployeeValidator> VALIDATOR_MAP = Map.of( StaffType.TECHNICAL, new TechnicalStaffValidator(), StaffType.BACK_OFFICE, new BackOfficeStaffValidator() // 新增员工类型时,只需要在这里添加新的映射关系即可 ); public static EmployeeValidator getValidator(StaffType staffType) { EmployeeValidator validator = VALIDATOR_MAP.get(staffType); if (validator == null) { throw new IllegalArgumentException("不支持的员工类型: " + staffType); } return validator; } }
优化后的客户端代码会非常简洁,彻底摆脱条件判断:
Employee employee = ...; Predicate<Employee> validator = EmployeeValidatorFactory.getValidator(employee.staffType()) .build(employee); boolean isValid = validator.test(employee);
方案2:结合枚举+策略模式,让类型与验证器直接绑定
如果你的StaffType是枚举类型,可以直接把验证器的创建逻辑内嵌到枚举中,实现类型与验证器的强绑定:
public enum StaffType { TECHNICAL(() -> new TechnicalStaffValidator()), BACK_OFFICE(() -> new BackOfficeStaffValidator()); private final Supplier<EmployeeValidator> validatorSupplier; StaffType(Supplier<EmployeeValidator> validatorSupplier) { this.validatorSupplier = validatorSupplier; } public EmployeeValidator getValidator() { return validatorSupplier.get(); } }
客户端调用会更直观:
Employee employee = ...; Predicate<Employee> validator = employee.staffType() .getValidator() .build(employee);
方案3:优化原接口的语义细节
看你原接口中的getCommonRules(Employee employee)方法,参数employee其实并没有被使用(因为内部的验证方法都是返回Predicate<Employee>,本身会接收Employee参数)。可以优化接口设计,让语义更清晰:
public interface EmployeeValidator { // 去掉不必要的employee参数,Predicate本身用于测试Employee Predicate<Employee> build(); static Predicate<Employee> getCommonRules() { return validateAge().and(validateGender()); // 注意原拼写Genger修正为Gender } private static Predicate<Employee> validateAge() { return emp -> emp.getAge() >= 18 && emp.getAge() <= 65; } private static Predicate<Employee> validateGender() { return emp -> emp.getGender() != null && Arrays.asList("M", "F", "O").contains(emp.getGender()); } }
对应的实现类也同步调整:
class BackOfficeStaffValidator implements EmployeeValidator { @Override public Predicate<Employee> build() { return EmployeeValidator.getCommonRules().and(validationsOnDirectReports()); } private Predicate<Employee> validationsOnDirectReports() { return emp -> emp.getDirectReports() != null && !emp.getDirectReports().isEmpty(); } }
进阶方案:用组合模式实现灵活的规则扩展
如果未来需要更灵活的规则组合(比如某些员工需要额外的定制规则),可以把每个验证规则拆成独立的组件,用组合模式来组装验证器:
首先定义单个验证规则的接口:
public interface ValidationRule { boolean validate(Employee emp); } // 年龄规则 public class AgeRule implements ValidationRule { @Override public boolean validate(Employee emp) { return emp.getAge() >= 18 && emp.getAge() <= 65; } } // 性别规则 public class GenderRule implements ValidationRule { @Override public boolean validate(Employee emp) { return emp.getGender() != null && Arrays.asList("M", "F", "O").contains(emp.getGender()); } } // 后台员工专属规则 public class DirectReportsRule implements ValidationRule { @Override public boolean validate(Employee emp) { return emp.getDirectReports() != null && !emp.getDirectReports().isEmpty(); } }
然后创建一个组合式的验证器:
public class EmployeeValidator { private final List<ValidationRule> rules; private EmployeeValidator(List<ValidationRule> rules) { this.rules = rules; } public boolean validate(Employee emp) { // 所有规则都通过才算验证通过 return rules.stream().allMatch(rule -> rule.validate(emp)); } // 提供工厂方法创建不同类型的验证器 public static EmployeeValidator forTechnicalStaff() { return new EmployeeValidator(List.of(new AgeRule(), new GenderRule(), new TechnicalSpecificRule())); } public static EmployeeValidator forBackOfficeStaff() { return new EmployeeValidator(List.of(new AgeRule(), new GenderRule(), new DirectReportsRule())); } }
这种方式完全符合单一职责原则,每个规则只负责一项验证,新增规则或调整组合都不需要修改现有代码,扩展性极强。
内容的提问来源于stack exchange,提问作者Govinda Sakhare
相关产品推荐
相关产品推荐

