Reputation: 2546
I try to create a DSL Java API with the Builder Pattern on Generics Type.
I have the following class:
public class Rule<T> {
private Predicate<T> condition;
public ConditionBuilder<T> when() {
return new ConditionBuilder<>(this);
}
//setter and getter
}
and the following ConditionBuilder class:
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;
}
}
I try to find a solution to set the Generic Type on the fly as an Integer (resp. String) for the condition1 (resp. condition2).
Is there any Pattern or solution to avoid doing instanceof
checking ?
Upvotes: 1
Views: 333
Reputation: 33496
I would use a factory pattern instead, because the builder pattern does not fit this situation. Using generics implies that you will accept any type, and so making condition
require a specific type is a waste of the generics.
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;
}
}
Upvotes: 0
Reputation: 140484
You can't do this with member methods on ConditionBuilder<T>
, since you've already constructed parent
before you invoke either of the conditionX
methods. As such, you can't constrain the instance "after the fact".
The way I'd do this is by making the Rule<T>
a parameter of a static method. Then you can use something like:
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;
}
Upvotes: 1