有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用于大型验证任务的java是责任链模式的好选择吗?

我需要建立一个流程,根据大约200条验证规则验证记录。记录可以是10种类型中的一种。从验证规则到记录类型有一些分割,但存在很多重叠,这使我无法清晰地将验证规则组合起来

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


共 (2) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    验证通常是一种复合模式。当你分解它时,你想把你想做的和你想做的分开,你得到:

    如果foo是有效的 那就做点什么

    这里我们有一个抽象的是有效的警告:这段代码是从current中提取的,类似的例子,所以你可能会发现缺少的符号等等。但这就是你了解的情况。此外

    Result
    

    对象包含有关故障的消息以及简单状态(true/false)。 这让你可以选择只问“通过了吗?”vs.“如果失败了,告诉我原因”

    QuickCollection
    

    QuickMap
    

    是一种方便的课程,只需分配给一名代表,就可以学习任何课程并快速将其转化为受人尊敬的类型。例如,在本例中,这意味着您的复合验证器已经是一个集合,可以进行迭代

    您的问题中有一个次要问题:“干净绑定”如“类型a”->;规则{a,b,c}”和“类型b”->;规则{c,e,z}”

    这很容易用地图来管理。不完全是Command pattern但很接近

    Map<Type,Validator> typeValidators = new HashMap<>();
    

    为每个类型设置验证器,然后创建类型之间的映射。如果你正在使用Java,这真的是最好的bean配置,但是肯定使用dependency injection

        public interface Validator<T>{
        
        
            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<String> {
        
        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<String> {
        
            @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<Validator> implements Validator<String> {
    
    
    public CompositeValidator(Collection<Validator> 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<Validator,Result> implements Result {
            private Integer appliedCount;
    
            private CompositeResult(Integer appliedCount) {
                super.delegate = VdcCollections.delimitedMap(new HashMap<PasswordRule, Result>(), " >",", ");
                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<String> pwRule = new CompositeValidator<String>(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);