我有一小组验证类,我已经创建了很好的服务,但是现在我需要更新它们以处理优先级规则。如果满足高优先级规则,那么我不需要再运行任何验证,因为我们只会告诉用户一条错误消息,而不是将整组消息添加到用户。
以下是我所拥有的课程集:
//Rule.java
public interface Rule<T> {
List<ErrorMessage> validate(T value);
}
//ValidationStrategy.java
public interface ValidationStrategy<T> {
public List<Rule<? super T>> getRules();
}
//Validator.java
public class Validator<T> implements Rule<T> {
private List<Rule<? super T>> tests = new ArrayList<Rule<? super T>>();
public Validator(ValidationStrategy<T> type) {
this.tests = type.getRules();
}
public List<ErrorMessage> validate(T value) {
List <ErrorMessage> errors = new ArrayList<ErrorMessage>();
for (Rule<? super T> rule : tests) {
errors.addAll(rule.check(value));
}
return errors;
}
}
我在修改此代码以处理优先级规则时遇到一些问题。当然有一些东西我可以修改使用而不是引入规则引擎。
理想情况下,我可以创建这样的规则:
private static final Rule<SomeClass> ensureAllFieldsNotBlank = new Rule<SomeClass>(RulePriority.HIGHEST) {
public List<ErrorMessage> check(SomeClass someClass) {
List<ErrorMessage> errors = new ArrayList<ErrorMessage>();
if (StringUtils.isBlank(someClass.getValue1())
&& StringUtils.isBlank(someClass.getValue2())
&& StringUtils.isBlank(someClass.getValue3())) {
errors.add("Provide a response for \"" + someClass.getName() + "\"");
}
return errors;
}
};
编辑更新的课程:
//ValidationStrategy.java
public interface ValidationStrategy<T> {
public List<Rule<? super T>> getRules(RulePriority rulePriority);
}
//RulePriority.java
public enum RulePriority { HIGHEST, DEFAULT, LOWEST; }
//Validator.java
public class Validator<T> implements Rule<T> {
private List<Rule<? super T>> tests = new ArrayList<Rule<? super T>>();
private ValidationStrategy<T> validationStrategy;
public Validator(ValidationStrategy<T> validationStrategy) {
this.validationStrategy = validationStrategy;
for (RulePriority rp : RulePriority.values()) {
this.tests.addAll(validationStrategy.getRules(rulePriority));
}
}
public List<ErrorMessage> validate(T value) {
List<ErrorMessage> errors = new ArrayList<String>();
for (RulePriority rp : RulePriority.values()) {
for (Rule<? super T> rule : validationStrategy.getRules(rp)) {
errors.addAll(rule.validate(value));
}
if (errors.size() > 0) {
break;
}
}
return errors;
}
答案 0 :(得分:2)
如何创建一个抽象基类来处理规则比较:
abstract class PrioritizedRule<T> implements Rule<T>, Comparable<PrioritizedRule<T>>{
public int compareTo(PrioritizedRule<T> other){
//Implement something that compares rule priorities here.
//This will probably require support from the constructor, which-
//since this is abstract- must be Protected.
从那里开始,您的PrioritizedValidator(需要PrioritizedRule)将在Validate的开头对它的集合进行排序()(如果自上次验证后其规则集已被修改;这是对集合进行排序的正确时间,因为我们没有如果有连续的修改,我们想要在每次修改时重复排序,或者如果我们不需要,则进行排序),如果错误消息列表在转换过程中非空,则Validate循环应提前输出规则优先级之间:
public List<ErrorMessage> validate(T value) {
if(ruleSetModified){
//be careful: validate becomes unsafe for multithreading here, even if you
//aren't modifying the ruleset; if this is a problem, implement locking
//inside here. Multiple threads may try to sort the collection, but not
//simultaneously. Usually, the set won't be modified, so locking before
//the test is much, much slower. Synchronizing the method is safest,
//but carries a tremendous performance penalty
Collections.sort(rule);
ruleSetModified = false;
}
List <ErrorMessage> errors = new ArrayList<String>();
PrioritizedRule prev = null;
for (PrioritizedRule<? super T> rule : tests) {
if(prev != null && prev.compareTo(rule) != 0 && !errors.isEmpty()){
return errors;
}
errors.addAll(rule.check(value));
prev = rule;
}
return errors;
}
我不确定你的意思是“......没有引入规则引擎”,但定义规则来排序自己可能是最优雅的方法。但是要小心 - 任何两个PrioritizedRule-s必须相互比较,这就是为什么我建议将PrioritizedRule作为抽象基础而不是接口,因为这是compareTo实现需要生存的地方,以保持一致性。你的compareTo不需要与equals保持一致,除非你试图将你的集合保存在一个排序集中,这个集合永远不能很好地结束(PrioritizedRule不能足够意识到它与equals一致!),所以不要尝试
或者,实现Comparator&gt;,但同样需要修改您的Rule接口以显示足够的信息以进行排序。