2016-07-12 7 views
1

Я пытаюсь создать DSL Java API с шаблоном Builder для типа Generics.Java Generics Type DSL with Builder Шаблон

У меня есть следующий класс:

public class Rule<T> { 

    private Predicate<T> condition; 

    public ConditionBuilder<T> when() { 
    return new ConditionBuilder<>(this); 
    } 

    //setter and getter 

} 

и следующий класс ConditionBuilder:

public class ConditionBuilder<T> { 

    private Rule<T> parent; 

    public ConditionBuilder(Rule<T> parent) { 
    this.parent = parent; 
    } 

    public ConditionBuilder<T> condition1() { 
    parent.setCondition(l -> l == 0); // I would like an Integer 
    return this; 
    } 

    public ConditionBuilder<T> condition2() { 
    parent.setCondition(l -> l.length() > 3); // I would like a String 
    return this; 
    } 

} 

я пытаюсь найти решение для установки общего типа на лету как Integer (соотв. String) для условия 1 (соответственно условие 2).

Есть ли какой-либо шаблон или решение, чтобы избежать выполнения instanceof проверки?

+0

Можете ли вы описать более широкую задачу, которую вы пытаетесь выполнить? Зачем вам нужно «условие1» и «условие2»? Почему бы не использовать параметр «Предикат»? Не используйте дженерики, если вы не хотите использовать общие типы. – 4castle

ответ

1

Вы не можете сделать это с помощью методов-членов на ConditionBuilder<T>, так как вы уже создали parent, прежде чем вы вызовете любой из методов conditionX. Таким образом, вы не можете ограничить экземпляр «после факта».

Как я могу это сделать, сделав параметр Rule<T> параметром статического метода. Тогда вы можете использовать что-то вроде:

static ConditionBuilder<Integer> condition1(ConditionBuilder<Integer> parent) { 
    parent.setCondition(l -> l == 0); 
    return parent; 
} 

static ConditionBuilder<String> condition2(ConditionBuilder<String> parent) { 
    parent.setCondition(l -> l.length() > 3); 
    return parent; 
} 
+0

(Обратите внимание, что 'Integer' является окончательным, поэтому' T extends Integer' является избыточным. Может также просто использовать 'Integer' напрямую) –

+0

Это разрушит шаблон построителя. Я все еще не понимаю, какую роль эти методы будут иметь. Я чувствую, что они не должны существовать, если OP собирается следовать шаблону строителя. – 4castle

+0

@ 4castle на самом деле не имеет значения, разрушает ли он шаблон; нет другого (очевидного) способа повлиять на такое ограничение во время компиляции. –

0

Я бы использовал шаблон фабрики, потому что шаблон строителя не соответствует этой ситуации. Использование дженериков подразумевает, что вы примете какой-либо тип, и поэтому для condition требуется определенный тип - это отходы дженериков.

public class Rule<T> { 
    private Predicate<T> condition; 
    //setter and getter 
} 

class ConditionFactory { 
    public static Rule<Integer> intCondition() { 
    Rule<Integer> rule = new Rule<>(); 
    rule.setCondition(l -> l == 0); 
    return rule; 
    } 

    public static Rule<String> strCondition() { 
    Rule<Integer> rule = new Rule<>(); 
    rule.setCondition(l -> l.length() > 3); 
    return rule; 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^