我有一些看起来像这样的东西:
public boolean isValidObject(SomeObject obj){
if(obj.getField() == null){
LOG.error("error code 1");
return false;
}
if(obj.getField().getSize() > 500){
LOG.error("error code 2");
return false;
}
......
if(someCondition()){
log something
return false;
}
return true;
}
使用lambdas在java 8中编写这个最干净的方法是什么?
答案 0 :(得分:11)
为此使用多态。为每个逻辑验证器创建一个类,并将它们链接到列表中。这里有你需要的很好的答案: https://stackoverflow.com/a/23501390/1119473
public interface Validator<SomeObject>{
public Result validate(SomeObject object);
}
实现:
public class SomeFieldSizeValidator implements Validator<SomeObject> {
@Override
public Result validate(SomeObject obj) {
// or you can return boolean true/false here if it's enough
return obj.getField().getSize() > 500 ? Result.OK : Result.FAILED;
}
}
调用验证链:
List<Validator> validators = ... create ArrayList of needed Validators
for (Validator v : validators) {
if (!v.validate(object)) {
... throw exception, you know validator and object here
}
答案 1 :(得分:3)
我可能会返回错误,但这仍然会使用一些if <#p>。
public String isValidObject(SomeObject obj){
if (obj.getField() == null) return "error code 1";
if (obj.getField().getSize() > 500) return "error code 2";
......
if (someCondition()) return "something";
return OK;
}
通过这种方式,您可以对此方法进行单元测试,以查看它是否返回了您对不同无效对象所期望的错误。
我想摆脱50条if / else语句。
如果您有50个条件并且它们都有不同的结果,则需要进行50次检查。你可以改变这样的结构。
static final Map<Predicate<SomeObject>, String> checks = new LinkedHashMap<>();
static {
checks.put((Predicate<SomeObject>) o -> o.getField() == null, "error code 1");
checks.put((Predicate<SomeObject>) o -> o.getField().getSize() > 500, "error code 2");
}
public String isValidObject(SomeObject obj) {
for (Predicate<SomeObject> test : checks.keySet())
if (test.test(object))
return checks.get(test);
return OK;
}
然而,就个人而言,这并不是更清楚,并且更难以调试,例如断点。
答案 2 :(得分:3)
我建议使用不同方法的解决方案:考虑使用Validator对象。含义:不是将所有检查放在同一个方法中,而是将每个检查放在自己的类中!
定义一些提供验证方法的Validator接口。验证失败时,该方法应抛出一些ValidationException(该异常可能包含错误代码+消息)。
然后你创建了许多小类,每个小类都实现了该接口。
最后一步:创建一个列表,在其中放置每个impl类的一个对象。现在,您的代码归结为迭代该列表,并将每个impl应用于另一个。
这解耦了您的验证步骤,添加新/其他检查变得非常容易。
答案 3 :(得分:3)
使用java.util.function.Predicate接口:
Predicate<SomeObject> p1 = (SomeObject so ) -> so.getField()!=null;
Predicate<SomeObject> p2 = (SomeObject so ) -> so.getField().getSize() > 500;
...
SomeObject someObject = new SomeObject();
Predicate<SomeObject> fullPredicate = p1.and(p2).and( ...
boolean result = fullPredicate.test(someObject);
除了这将给你50个Predicate一行定义,它们会更紧凑。
答案 4 :(得分:2)
我不确定lambdas
如何在这里有用。
如果你使用了很多'if else'来处理很多业务规则,那么一个选择就是尝试一些rule engines
。一个简单而最好的选择是EasyRules
Easy rules
非常方便且易于实施。这将使您的业务逻辑代码看起来非常干净。
答案 5 :(得分:1)
如果您特别希望使用lambda,它们与enum
:
public enum SomeValidators {
E1 (1, o -> o.getField() == null),
E2 (2, o -> o.getField().getSize() > 500)
;
final int code;
final Predicate<SomeObject> predicate;
SomeValidators(int code, int predicate) {
this.code = code;
this.predicate = predicate;
}
}
然后您可以使用它来复制if-else if流程,如下所示:
boolean isValidObject(SomeObject o) {
Optional<SomeValidators> firstError =
Arrays.stream(SomeValidators.values())
.filter(v -> v.predicate.apply(o))
.findFirst();
firstError.ifPresent(e -> LOG.error("error code " + e.code));
return firstError.isPresent();
}