2

This is something I've encountered a few times and haven't been able to find a satisfying answer yet. This seems pretty stupid, but after googling this for a while I couldn't come up with something good.

Let's say I have a class with 20 instance variables, each of which is optional (will be initialized or not).

Now I want my constructor(s) to handle all the cases, in case of a few instance variables it's fine and I can just create constructors with different signatures, but here I have 20, so I would need 2^20=1,048,576 constructors to handle all the cases ! That seems ... not very optimal, don't you agree?

So since with this brute force approach I basically have to construct 2^n constructors, where n is the number of instance variables, I want to find a better way to do it.

I've seen a couple solutions for this problem, but I believe they all on assumptions on the data, but in my case each of these variables can be initialized or not at random, I have no way of knowing that before initialization.

I'm looking for some design patterns or ideas that I could apply to make my code a bit more ... maintainable (no don't worry I didn't create 1M+ constructors :)

Thanks.

Charles Menguy
  • 40,830
  • 17
  • 95
  • 117
  • 1
    bean pattern. Constructor has no args, all params go in through setters. – bmargulies Apr 15 '12 at 02:07
  • 1
    that seems silly, I said I have 20 instance variables but in reality I have more, I don't want to call 20 different setters ! It could be in inconsistent state partway through its execution, this seems like a very bad solution. – Charles Menguy Apr 15 '12 at 02:10
  • And this also forbids me to make my class immutable. – Charles Menguy Apr 15 '12 at 02:11

3 Answers3

7

Try the Builder pattern:

http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html

duffymo
  • 305,152
  • 44
  • 369
  • 561
5

Combine the Bean pattern with a Builder. YourObject will not have inconsistent state halfway through its construction, but it will still take 20+ set operations and you can make YourObject immutable (if you want) - but not YourObjectBuilder.

public class YourObject {
    private Type field1;
    private Type field2;
    private Type field3;
    ...
    YourObject ( Type field1 , Type field2 , Type field3 ... ) { }
}

public class YourObjectBuilder {
    private Type field1;
    private Type field2;
    private Type field3;
    ...

    public YourObjectBuilder() {
    }

    public YourObject make ( ) {
         return new YourObject ( field1 , field2 , field3 ... ) ;
    }

    public void setField1(Type t) {
        field1 = t;
    }

   public void setField2(Type t) {
        field2 = t;
   }

    public void setField3(Type t) {
        field3 = t;
    }
    ...
}
emory
  • 10,725
  • 2
  • 30
  • 58
0
public class YourObject {
    private Type field1;
    private Type field2;
    private Type field3;
    ...

    public YourObject() {
    }

    public void setField1(Type t) {
        field1 = t;
    }

   public void setField2(Type t) {
        field2 = t;
   }

    public void setField3(Type t) {
        field3 = t;
    }
    ...
}
Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • As I said in comment above, the problem with this kind or approach is that my object can be in inconsistent state partway through its construction ! That's very dangerous in my case and I can't really afford to do that. And you have to make you class mutable, which is something I don't want to. – Charles Menguy Apr 15 '12 at 02:10
  • @linker The object will be in an inconsistent state partway through its construction only if you pass it to some other method before you finish creating it. If you need to worry about mutability, you could create a flag to determine if the fields are settable, and toggle it when you're done creating your object. – Jeffrey Apr 15 '12 at 02:17
  • I was more talking in a multi-threaded context. You're right I could ensure the object is not accessed before it is done building, but that requires some extra effort to ensure thread-safety. – Charles Menguy Apr 15 '12 at 02:33