Builder (97) Design Pattern, Part 1 has an introduction to the “Gang of Four” Design Patterns book and gives an example where the builder pattern may be useful. Where I left off, we have a code snippet like this where the “Validator” class and its associated methods (setRequiredFields and validate) don’t yet exist.
The context around this is that we need a flexible way to validate the form. Sometimes first name and email are the only required fields and sometimes first name, email, and birth date are all required. Since we want to only give each class a single responsibility, we are shying away from the idea that validation logic lives inside this POJO. We want the POJO to delegate validation responsibility to a validator class.
It’s even more complicated than that, though! If email and birth date are both required fields, then we want to validate that they are actually formatted correctly. That will be a second level of validation beyond the question of “were they filled in?” If they are filled in, they may have been filled in incorrectly!
A common approach for creating a class flexible enough to accomodate all these cases is to hold some values as null. In our case, per the last code snippet, we opted to supply an array of Strings via setter injection into the Validator class. Another approach might be to have some boolean flags, that, if true, cause the validation of email and birth date. Then you either create a constructor which requires false being passed in for these flags or you have multiple constructors with different parameter lists that allow them to be filled in. You might have experienced something like this in your past, and know that it can get both messy and confusing.
In our approach, which is not much better, and maybe worse, the code might look something like this, with much of the logic removed so you can just look at the parts currently in context:
Hopefully you can see the nightmare we are already in, and the even bigger nightmare we might be headed for by this approach. A really important consideration when writing code like this is how many things can go wrong when you’ve designed a class a certain way. In this case, there are just so many things that can go wrong as far as bugs in the final code, and this class won’t be very maintainable either. What if we add a fourth field to the contact info form later, such as phone number? Are you going to come in here and add another method for phone number and keep remembering to pass an array of strings that includes “phonenumber?” Speaking of, are you going to hard code all the values like this into your required fields array? Will every method always have to be wrapped in an “if” statement that tells us whether that field existed on the form or not?
Before you answer any of those questions, let me just show a much better way of going about things, starting with the client code that uses the ContactInfo class. The thing I am asking you to envision here is: “What if the code handling the form submission can easily tell the POJO and the validator what to do?” And by the way, this is an example of the builder pattern in action.
This makes a lot more sense. The code handling the form submission is going to know what form it is getting and has a way in code to create a validator that accounts for the various cases involved. As you can see, not much needs to change here in order to omit birth date. The version without birth date would look like:
Basically, you just omit the “withBirthDateValidation” call and pass only the firstName and email variables into the withBlankFieldValidation call.
OK now we’ve hit our length limit again and we’ll have to save implementation of this bad boy until part 3.