我正在寻找链接Predicates并一起测试它们的能力。
思想
我们有谓词的条件(或其他):
1. P<T>, P<R>, P<S>
2. P<T>.and(P<T>) => P<T> as result P<T>.test(t1, t2)
3. P<T>.and(P<R>) => P<T,R> as result P<T,R>.test(t,r)
4. P<T>.and(P<R>.or(P<S>)) => P<T,R,S> as result P<T,R,S>.test(t,r,s)
我有模特
class User {
private String name;
private boolean isActive;
public User(String name, boolean isActive) {
this.name = name;
this.isActive = isActive;
}
//getters only...
}
顺序
public class Order {
private long createdAt;
private User user;
private Manager manager;
private boolean isApproved;
public Order(User user, Manager manager, long createdAt, boolean isApproved) {
this.user = user;
this.manager = manager;
this.createdAt = createdAt;
this.isApproved = isApproved;
}
// getters only ...
}
管理器
class Manager {
private ManagerCompetency competency;
private String name;
public Manager(String name, ManagerCompetency competency) {
this.name = name;
this.competency = competency;
}
//getters only...
}
结果我发现了类似的东西 为简短的OrderAcceptanceSpecification OAS
Boolean result = OAS.isUserCanCreateOrder()
.and(OAS.isOrderApproved())
.and(OAS.isOrderExpiredAfter(3600)).negate()
.and(
OAS.isOrderApproverCompetentAs(Competencies.HIGH)
.or(OAS.isOrderApproverCompetentAs(Competencies.MIDDLE)
).test(Order, Manager, User)
欢迎任何建议/改进。
UPD 我找到了类似的解决方案
public class ChainedPredicate<T> {
private T t;
private Predicate<T> predicate;
public ChainedPredicate(T t, Predicate<T> predicate) {
Objects.requireNonNull(t);
Objects.requireNonNull(predicate);
this.t = t;
this.predicate = predicate;
}
private ChainedPredicate(Predicate<T> predicate) {
Objects.requireNonNull(predicate);
this.predicate = predicate;
}
public Predicate<T> toPredicate() {
return t -> test();
}
public boolean test() {
return predicate.test(t);
}
public ChainedPredicate<T> and(ChainedPredicate<?> other) {
Objects.requireNonNull(other);
return new ChainedPredicate<T>(t -> test() && other.test());
}
public ChainedPredicate<T> or(ChainedPredicate<?> other) {
Objects.requireNonNull(other);
return new ChainedPredicate<T>(t -> test() || other.test());
}
public ChainedPredicate<T> negate() {
return new ChainedPredicate<T>(toPredicate().negate());
}
}
执行测试
public class TestChainedPredicate {
public static void main(String[] args) {
Predicate<Boolean> tp1 = x -> 1 >0;
Predicate<String> fp1 = x -> 1 <0;
Predicate<Integer> fp2 = x -> 1 <0;
ChainedPredicate<Boolean> p = new ChainedPredicate<Boolean>(true, tp1); //true
ChainedPredicate<String> p1 = new ChainedPredicate<String>("123", fp1); // false
ChainedPredicate<Integer> p2 = new ChainedPredicate<Integer>(100, fp2); // false
boolean result = p.and(p1.or(p2)).test(); // false
System.out.println(result + " expected : " + false + " : " + ((result==false) ? "OK" : "ERROR") );
result = p.or(p1.or(p2)).test();
System.out.println(result + " expected : " + true + " : " + ((result==true) ? "OK" : "ERROR"));
result = p1.or(p.and(p2)).test();
System.out.println(result + " expected : " + false + " : " + ((result==false) ? "OK" : "ERROR"));
result = p1.or(p.or(p2)).test(); // false
System.out.println(result + " expected : " + true + " : " + ((result==true) ? "OK" : "ERROR"));
result = p1.or(p.or(p2)).negate().test(); // false
System.out.println(result + " expected : " + false + " : " + ((result==false) ? "OK" : "ERROR"));
}
}
答案 0 :(得分:2)
正如方法签名所示,您只能链接相同类型的谓词。除非您的类共享超类,否则没有解决方法。
Predicate<T> and(Predicate<? super T> other)
Predicate<T> or(Predicate<? super T> other)
答案 1 :(得分:2)
看起来你过于复杂了。您的OrderAcceptanceSpecification
可能只包含两种方法:
static class OrderAcceptanceSpecification {
static Predicate<Order> isOrderApproved() {
return Order::isApproved;
}
static Predicate<Order> isOrderExpiredAfter(int seconds) {
return o -> System.nanoTime() - o.createdAt() > seconds;
}
}
假设您有一个如下所示的类:
class Order {
private final Manager manager;
private final User user;
....
您需要的Predicate
可以这样写:
Predicate<Order> predicate = OrderAcceptanceSpecification.isOrderApproved()
.and(x -> x.getUser().isActive())
.and(OrderAcceptanceSpecification.isOrderExpiredAfter(3600).negate())
.and(x -> x.getManager().getCompetency().equals(ManagerCompetency.HIGH)
|| x.getManager().getCompetency().equals(ManagerCompetency.MIDDLE));
我发现||
更清洁,而不是将lambda表达式转换为Predicate
并链接or
。