Wednesday 3 March 2010

"Bob" the Builder (pattern)

So, I've heard of Java constructors. These friendly little guys make an instance of an object when the program calls them, setting variables if necessary, making everything work the way you need to. Today, however, was the first time I'd heard of Builders.

Constructors can, sometimes, get really messy. "Setting variables if necessary" can get to the point where you have 20 variables to set and 18 of those are optional. It's nasty to program a constructor to properly handle optional variables and it's nasty to call a constructor with all of those variables. And who wants to print out a list of which variable comes when in the call to the constructor?

Hello, builders. Builders are like flexible constructors, but they require a bit more manipulation to set up properly. Basically a builder is a class placed inside the class you want to construct, and no constructor is made available for that class. Instead, you call the constructor for the builder (in Java syntax this means you call something like endgoal.builder() where endgoal is the thing being built), with any required values included in the () after builder. Then you continue calling optional values by adding .option1(), .option2(), and so on until the object is fully set up for you. All of the values that eventually go into your endgoal object are stored privately inside the builder class so as not to cause any funny business on the part of your outer class.

When you're all done, you call the endgoal.build() class to put it all together for you, as necessary.

What am I using this for? At the moment, validation on the text box used to enter Material Codes. Matcodes must be 11 characters long, consisting only of english alphabet letters. I convert the input to uppercase inside the material code interpreter's method, so it's not a big deal what case you use externally, but internally it does make a difference.

I realize that the matcode input is not the only text field I'm going to use, and in searching for the way to limit the maximum number of characters in a text field I've come to the conclusion that it requires making a so-called "Document" that tells the input box how to behave. This is easy enough, but why code a separate document for each text input when I can just create a builder?

For now I'm coding in the options to change the input to Upper/Lowercase depending on needs, to force the input to be alphabetical, numerical, or both, to set a maximum length onto the input, and finally to allow or disallow spaces in the input. In the case of my matcode text box, I'll call something like:


input.setDocument( new JTextFieldLimits.LimitBuilder()
.charLimit(11).toUpperCase().forceLetter()
.forceNoSpace().build() );

It looks a little nasty but for my sanity it's better than something more like:

input.setDocument( new JTextFieldLimits(true, 11,
true, false, true, false, false, true));

where I have to remember which position responds to which value every time I make a new input box. And that would be even longer if I come up with more options to throw in here. Don't forget that if all I want to do is disallow spaces, with the builder I can just do LimitBuilder().forceNoSpace().build() whereas with the other one I have to include all of the "false" values until the very end. And Java forbid I forget how many false values that adds up to.

The JTextFieldLimits class isn't quite finished yet, but it's progressing smoothly and I don't think I'll run into too many problems with it. Once that's done I'll get back to work on isolating the MatPolygonDraw class by having it build its own panels. I think I'll have both of those done before my next post.

Reference: http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html Thanks for the help!

No comments: