2017-08-16 86 views
1

我正在尋找鏈接謂詞的能力並一起測試它們。基於不同類型實現謂詞鏈接

思考

我們有謂詞條件(或其他人):

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... 
    } 

至於結果,我NEDD像 短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")); 

    } 

} 
+2

它看起來像所有的謂詞應該是類型的訂單.... –

+2

這裏的問題是什麼? –

+0

實現Chaining謂詞並一起測試它們。 –

回答

2

由於方法簽名表明,同一類型的,你只能鏈謂詞。沒有解決方法,除非你的類共享超類。

Predicate<T> and(Predicate<? super T> other) 

Predicate<T> or(Predicate<? super T> other) 
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

+0

在我看來,OrderAcceptanceSpecification是一組預定義的條件,用於驗證接受訂單的可用性,這就是爲什麼OrderAcceptanceSpecification類中的OrderOrderApproverCompetentAs。 –

+1

@ Anton.S你可以*至少*顯示你的類的結構,所以我們不會猜測 – Eugene

+1

@ Anton.S添加你的問題,而不是評論 – Eugene