4

Recently, I was asked in an interview to implement Builder Pattern in such a way that user cannot set a parameter B unless parameter A is set.

I suggested to pass A as a required parameter when constructing the Builder but he was not satisfied with my answer. I also suggested to throw IllegelStateException if A is not set when setting B but again he was not satisfied. Could anyone suggest how can we enforce user to set A before he sets B?

class Example{
private int A;
private int B;

public static class Builder{
}

}

rakku
  • 73
  • 6
  • 3
    You would need to create separate Builder classes, the first for setting the A, whereupon the returned value is an instance of the second Builder which is for setting B. – Andy Turner Jan 01 '19 at 09:35
  • @AndyTurner, say, i have another field C, I would not be able to set the value of C, if I had set the value of A first, as it would return the builder for field B. Or would I be able to? – Ankur Jan 01 '19 at 09:41

2 Answers2

2

To do it in plain Java, you would need to create separate Builder classes, the first for setting the A, whereupon the returned value is an instance of the second Builder which is for setting B.

One of the limitations of this approach is that it is very verbose, and doesn't scale well to having lots of optional parameters.

Alternatively, I have done this by writing a compiler plugin (I used Error Prone, since that is easiest to do with Google's build system, but there is no reason another tool couldn't be used) which checks the method call order.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
0

the main idea is to use a different return type in setA setB method, but those type must be the same type or subtype of the builder type.

public class ExampleBuilderImpl implements  FullExampleBuilder {
private int a;
private int b;



public Example createExample() {
    return new Example(a, b);
}

@Override
public PartExampleBuilder setB(int b) {
    this.b = b;
    return this;
}

@Override
public FullExampleBuilder setA(int a) {
    this.a = a;
    return this;
}


public static void main(String[] args) {


    ExampleBuilderImpl builder = new ExampleBuilderImpl();

    // compiler error
   //       builder.setB(1).setA();

    builder.setA(1).setB(2);

}

}

public interface FullExampleBuilder extends PartExampleBuilder {
    FullExampleBuilder setA(int a);

}



public interface PartExampleBuilder {
    PartExampleBuilder setB(int b);
}
宏杰李
  • 11,820
  • 2
  • 28
  • 35