对于一个大的验证任务是责任模式的一个很好的赌注? [英] For a large validation task is chain of responsibility pattern a good bet?

查看:136
本文介绍了对于一个大的验证任务是责任模式的一个很好的赌注?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要构建一个过程,该过程将验证约200条验证规则的记录。记录可以是〜10种。有一些从验证规则到记录类型的分段,但是存在很多重叠,这阻碍了我将整个验证规则进行干净的分类。

I need to build a process which will validate a record against ~200 validation rules. A record can be one of ~10 types. There is some segmentation from validation rules to record types but there exists a lot of overlap which prevents me from cleanly binning the validation rules.

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

During my design I'm considering a chain of responsibility pattern for all of the validation rules. Is this a good idea or is there a better design pattern?

推荐答案

验证通常是一个复合模式。当你把它分解掉的时候,你想从你想要做的 中分离你想要的,你会得到:

Validation is frequently a Composite pattern. When you break it down, you want to seperate the what you want to from the how you want to do it, you get:

如果foo有效
然后做某事。

If foo is valid then do something.

这里我们有抽象有效 - 警告:这段代码已经从currrent,类似的例子解除了,所以你可能会发现缺少符号系统等等。但这是你得到的照片。另外,

Here we have the abstraction is valid -- Caveat: This code was lifted from currrent, similar examples so you may find missing symbology and such. But this is so you get the picture. In addition, the

Result

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

Object contains messaging about the failure as well as a simple status (true/false). This allow you the option of just asking "did it pass?" vs. "If it failed, tell me why"

QuickCollection

QuickMap

只需分配给代表,就可以使用任何类的便利类,并快速将它们转换成这些受尊敬的类型。对于这个例子,这意味着你的组合验证器已经是一个集合,可以被重复使用,例如。

Are convenience classes for taking any class and quickly turning them into those respected types by merely assigning to a delegate. For this example it means your composite validator is already a collection and can be iterated, for example.

你的问题有一个次要问题:干净地绑定 ,类型A - >规则{a,b,c}和类型B - >规则{c,e,z}

You had a secondary problem in your question: "cleanly binding" as in, "Type A" -> rules{a,b,c}" and "Type B" -> rules{c,e,z}"

用地图管理。不完全是命令模式,但关闭

This is easily managed with a Map. Not entirely a Command pattern but close

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

为每个类型设置验证器,然后在类型之间创建一个映射。如果您使用Java,但最好使用Bean配置,但绝对使用依赖注入

Setup the validator for each type then create a mapping between types. This is really best done as bean config if you're using Java but Definitely use 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();
    }
    }

现在一些简单的实现来显示: p>

Now some simple implementations to show the point:

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();
    }

}

现在这里是一个复合: / p>

Now here is a composite:

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);

这篇关于对于一个大的验证任务是责任模式的一个很好的赌注?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆