对于一个大的validation任务是责任链模式的一个好赌注?

我需要构建一个过程,它将根据~200个validation规则validation记录。 记录可以是~10种类型中的一种。 从validation规则到记录类型存在一些细分,但存在大量重叠,这使我无法对validation规则进行干净整理。

在我的设计过程中,我正在考虑所有validation规则的责任链模式。 这是一个好主意还是有更好的设计模式?

validation通常是复合模式。 当你分解它时,你想要从你想要的方式分离你想要的东西 ,你会得到:

如果foo有效则执行某些操作。

这里我们有抽象是有效的 – 警告:这个代码是从类似的例子中解除的,所以你可能会发现缺少符号系统等等。 但这是你得到的照片。 除此之外

Result 

对象包含有关失败的消息以及简单状态(true / false)。 这允许你选择只是问“它通过了吗?” 与“如果失败,告诉我为什么”

 QuickCollection 

 QuickMap 

通过仅仅分配给代表来获取任何类并快速将它们转换为那些受尊重的类型的便利类。 对于此示例,这意味着您的复合validation器已经是一个集合,并且可以进行迭代。

您的问题中存在次要问题:“干净地绑定”,如“类型A” – >规则{a,b,c}“和”类型B“ – >规则{c,e,z}”

这可以通过Map轻松管理。 不完全是Command模式但是关闭

 Map typeValidators = new HashMap<>(); 

为每种类型设置validation器,然后在类型之间创建映射。 如果您使用Java但绝对使用dependency injection,那么最好以bean配置完成

  public interface Validator{ public Result validate(T value); public static interface Result { public static final Result OK = new Result() { @Override public String getMessage() { return "OK"; } @Override public String toString() { return "OK"; } @Override public boolean isOk() { return true; } }; public boolean isOk(); public String getMessage(); } } 

现在一些简单的实现来说明这一点:

 public class MinLengthValidator implements Validator { private final SimpleResult FAILED; private Integer minLength; public MinLengthValidator() { this(8); } public MinLengthValidator(Integer minLength) { this.minLength = minLength; FAILED = new SimpleResult("Password must be at least "+minLength+" characters",false); } @Override public Result validate(String newPassword) { return newPassword.length() >= minLength ? Result.OK : FAILED; } @Override public String toString() { return this.getClass().getSimpleName(); } } 

这是另一个我们将结合

 public class NotCurrentValidator implements Validator { @Autowired @Qualifier("userPasswordEncoder") private PasswordEncoder encoder; private static final SimpleResult FAILED = new SimpleResult("Password cannot be your current password",false); @Override public Result validate(String newPassword) { boolean passed = !encoder.matches(newPassword,user.getPassword()); return (passed ? Result.OK : FAILED); } @Override public String toString() { return this.getClass().getSimpleName(); } } 

现在这是一个复合:

 public class CompositePasswordRule extends QuickCollection implements Validator { public CompositeValidator(Collection rules) { super.delegate = rules; } public CompositeValidator(Validator... rules) { super.delegate = Arrays.asList(rules); } @Override public CompositeResult validate(String newPassword) { CompositeResult result = new CompositeResult(super.delegate.size()); for(Validator rule : super.delegate){ Result temp = rule.validate(newPassword); if(!temp.isOk()) result.put(rule,temp); } return result; } public static class CompositeResult extends QuickMap implements Result { private Integer appliedCount; private CompositeResult(Integer appliedCount) { super.delegate = VdcCollections.delimitedMap(new HashMap(), "-->",", "); this.appliedCount = appliedCount; } @Override public String getMessage() { return super.delegate.toString(); } @Override public String toString() { return super.delegate.toString(); } @Override public boolean isOk() { boolean isOk = true; for (Result r : delegate.values()) { isOk = r.isOk(); if(!isOk) break; } return isOk; } public Integer failCount() { return this.size(); } public Integer passCount() { return appliedCount - this.size(); } } } 

现在是一个使用片段:

 private Validator pwRule = new CompositeValidator(new MinLengthValidator(),new NotCurrentValidator()); Validator.Result result = pwRule.validate(newPassword); if(!result.isOk()) throw new PasswordConstraintException("%s", result.getMessage()); user.obsoleteCurrentPassword(); user.setPassword(passwordEncoder.encode(newPassword)); user.setPwExpDate(DateTime.now().plusDays(passwordDaysToLive).toDate()); userDao.updateUser(user); 

责任链意味着必须进行validation。 我可能会使用类似于策略模式的东西,其中有一组应用于特定记录类型的validation策略。 然后,您可以使用工厂检查记录并应用正确的validation集。