如何在Java中链接检查

Chr*_*311 3 java refactoring chaining

考虑下面的类

public class MyClass {

    private Integer myField;
    private Result result;
    // more global variables

    public MyResult check(Integer myParameter) {
        init(myParameter);

        if (myField < 0) {
            result.setErrorMessage("My error message");
            return result;
        }

        // a lot more 'checks' like above where something may be written
        // to the error message and the result gets returned.
    }

    private void init(Integer myParameter) {
        result = new Result();
        result.setExistsAnnouncement(/*search a certain object via crudService with myParameter*/);
        // initialize other global variables including myField
    }

}
Run Code Online (Sandbox Code Playgroud)

问题在于check上面的方法太长了,并且有很多 return语句。我想到了一些重构,但是仍然不确定该怎么做。我在考虑类似连锁模式的东西。然后,我将实现几个检查器类,这些检查器类将调用链中的下一个检查器,或者返回result相应的errorMessage

但是后来我有了一个更好的主意(至少我是这么认为的):为什么表现得不像Java 8?我想用类似的Try- Success- Failure-pattern。但是我不知道如何实现这一点。我在想类似的东西:

entrancePoint.check(firstChecker)
    .check(secondChecker)
    .check // and so on
Run Code Online (Sandbox Code Playgroud)

这个想法是:当check失败时,它将表现为,Optional.map()并返回类似的内容Optional.EMPTY(或在这种情况下,类似于的内容Failure)。如果check成功的话应该去和做下检查(返回Success)。

您有做类似事情的经验吗?

Jay*_*Jay 5

当我们考虑验证时,通常是复合模式。它大致描述为:

如果此方法有效,则执行SOMETHING

而且,正如您所强加的那样,您希望将多个检查程序链接在一起以在其区域中执行验证,因此可以实施“责任链”模式。

考虑一下:

您可以有一个Result对象,其中可以包含有关失败的消息以及简单的true / false。

您可以拥有一个ValidatorObject,该对象进行所需的任何验证并返回的实例Result

public interface Result {  
    public boolean isOk();
    public String getMessage();
}

// We make it genric so that we can use it to validate
// any type of Object that we want.
public interface Validator<T> {
    public Result validate(T value);
}
Run Code Online (Sandbox Code Playgroud)

现在,当您说要使用多个检查器来验证“ X”时,您要强加一个验证规则,该规则只是Validator对象的集合,而只是其Validator自身的实例。话虽如此,您不能再使用该Result对象来检查规则的验证结果。您将需要一个Result可以将结果保持为的复合对象{Validator=Result}。看起来不是像的实现HashMap<Validator, Result>吗?是的,因为是。

现在,您可以实现RuleCompositeResult

public class Rule extends ArrayList<Validator> implements Validator {

    public Rule(Validator<?> ... chain) {
        addAll(Arrays.asList(chain));
    }

    public Object validate(Object target) {
        CompositeResult result = new CompositeResult(size());
        for (Validator rule : this) {
            Result tempResult = rule.validate(value);
            if (!tempResult.isOk())
                result.put(rule, tempResult);
        }
        return result;
    }
}

public class CompositeResult extends HashMap<Validator, Result> implements
        Result {

    private Integer appliedCount;

    public CompositeResult(Integer appliedCount) {
        this.appliedCount = appliedCount;
    }

    @Override
    public boolean isOk() {
        boolean isOk = true;
        for (Result r : values()) {
            isOk = r.isOk();
            if (!isOk)
                break;
        }
        return isOk;
    }

    @Override
    public String getMessage() {
        return toString();
    }

    public Integer failCount() {
        return size();
    }

    public Integer passCount() {
        return appliedCount - size();
    }

}
Run Code Online (Sandbox Code Playgroud)

就是这样!现在,要实现您的检查器:

public class Checker1 implements Validator<Integer> {
    /* Implementation */
}

public class CheckerN implements Validator<Integer> {
    /* Implementation */
}
Run Code Online (Sandbox Code Playgroud)

现在该进行验证了:

Validator<Integer> checkingRule = new Rule(new Checker1(), new CheckerN());
CompositeResult result = checkingRule.validate(yourParameter);
if (result.isOk()) 
    System.out.println("All validations passed");
else
    System.out.println(result.getFailedCount() + " validations failed");
Run Code Online (Sandbox Code Playgroud)

简单而整洁。

在公共仓库中上传了一个示例供您试用