0

I need to build objects of a class which has 3 fields: A, B and C. A valid object has at least one of A, B or C set by the user. I looked into the Builder Pattern, which is close to what I want, but only 1 field is made mandatory. I want that 1 field which must be set to be any one of the 3 that I have. Any suggestions?

My alternative is to use 7 constructors (for {A}, {B}, {C}, {A,B}, {B,C}, {A,C}, {A,B,C})

ask
  • 2,160
  • 7
  • 31
  • 42
  • 1
    "but the field that must be set cannot be changed" <-- I fail to understand your objection? Can you explain? The builder pattern is powerful among other things because it can check for conditions such as yours prior to performing the actual build... – fge Jun 09 '13 at 12:46
  • 1
    the builder pattern actually lets you decide if the builder options you passed are valid before building the actual object, I don't see the problem here. E.g.: new Bulder().withA(a).build() succeeds, new Builder().build() fails – Giovanni Caporaletti Jun 09 '13 at 12:49

2 Answers2

3

You can use a builder for that. Short example with only two fields instead of three:

public final class MyBuilder
{
    private X a, b;

    public MyBuilder withA(X a)
    {
        b = null;
        this.a = a;
        return this;
    }

    public MyBuilder withB(X b)
    {
        a = null;
        this.b = b;
        return this;
    }

    public MyClass build()
    {
        if (a == null && b == null)
            barf(); // <-- throw exception here
        // A and B inherit MyClass
        return a != null ? new A(a) : new B(b);
    }
}
fge
  • 119,121
  • 33
  • 254
  • 329
  • 1
    Thank you. I should have given more than a perfunctory look into the Builder pattern. – ask Jun 09 '13 at 12:51
  • You can even do better than that... The builder pattern is insanely powerful – fge Jun 09 '13 at 12:53
1

You can force A, B, or C to be passed in the build() method:

class ValidBuilder {
  public ValidBuilder withA(Object a) {}
  public ValidBuilder withB(Object b) {}
  public ValidBuilder withC(Object c) {}

  public ValidObject buildA(Object a) { }
  public ValidObject buildB(Object b) { }
  public ValidObject buildC(Object c) { }
}
Garrett Hall
  • 29,524
  • 10
  • 61
  • 76