前些天在阅读《多条件判断场景中规则执行器的设计》https://juejin.cn/post/6951764927958745124觉得作者实现的不错,但考虑到java8已经提供了功能强大的predicate,特基于predicate做了一个简单的实现。
public class RuleServiceX<T> {
private Predicate and;
private Predicate or;
public static RuleServiceX create() {
return new RuleServiceX();
}
public RuleServiceX and(Predicate and) {
this.and= and;
return this;
}
public RuleServiceX or(Predicate or) {
this.or= or;
return this;
}
public boolean execute(T dto) {
boolean result= false;
if(and!=null){
result = and.test(dto);
}
if(!result) {
if (or != null) {
result = or.test(dto);
}
}
return result;
}
public static Predicate ruleAnd(Predicate... operations) {
return Arrays.stream(operations).reduce(Predicate::and).orElse(t -> true);
}
public static Predicate ruleOr(Predicate... operations) {
return Arrays.stream(operations).reduce(Predicate::or).orElse(t -> true);
}
public static Predicate operation(
Function extractor,
Predicate condition) { return t -> condition.test(extractor.apply(t)); } }
@Data
public class RuleDto {
private String address;
private int age;
private String name;
private String subject;
}
@org.junit.Test
public void executeX() {
RuleDto dto = new RuleDto();
dto.setAge(19);
dto.setName("张三");
dto.setAddress("北京");
dto.setSubject("数学");
Predicate ruleAnd = RuleServiceX.ruleAnd(
operation(RuleDto::getAge, p -> p >= 20),
operation(RuleDto::getAddress, p -> p.startsWith("北京")),
operation(RuleDto::getName, p -> p.contains("张三")));
Predicate ruleOr = RuleServiceX.ruleOr(
operation(RuleDto::getAge, p -> p >= 10),
operation(RuleDto::getAddress, p -> p.startsWith("a")),
operation(RuleDto::getName, p -> p.contains("a")));
RuleServiceX serviceX = new RuleServiceX<RuleDto>();
boolean ruleResult = serviceX
.create()
.and(ruleAnd)
.or(ruleOr)
.execute(dto);
System.out.println("this student rule execute result :" + ruleResult);
}
public static Predicate operation(
Function extractor,
Predicate condition) {
return t -> condition.test(extractor.apply(t)); }
参考资料: