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. Builder (97) Design Pattern, Part 2 talks more in-depth about different ways to approach a common problem in web development, form validation, and ends with a wish for client code that looks a particular way. Namely:
Now, in part 3, we’ll talk about how to get to this envisioned promise land.
First, we need something of a framework for performing validation that is very flexible. So I propose an interface called “ValidationRule” which provides a couple of simple elements as seen here:
Awesome! Now we have an interface in place which can encapsulate logic around any type of validation on a string. The “validate” method here will implement that logic. In our case we have been following a real world example where we might be handling a form with only a name and email field, or we might get the version with a name, email, and a birth date! So you can envision that we’ll have three instances of ValidationRule to cover all the cases:
- Field is not blank (which will apply to all fields)
- An email is formatted correctly as an email
- A birthdate is formatted correctly in the format we choose (which will be YYYY-MM-DD)
Now we can make use of the builder pattern to create this! The builder pattern will not only encapsulate these three rules, but provide a whole framework around how to easily create a “Validator” object that has any combination of these rules:
In the book Design Patterns, Gamma, Helm, Johnson, and Vlissides define the builder as a way to:
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
In the ValidatorBuilder example, we have made an entirely flexible and (more importantly) fluent way for creating a “Validator.” The “Validator” keeps a list of ValidationRule (the interface defined above) and when you call the Validator class’ validate method, it in turn calls validate on all the ValidationRules in its list.
Where the ValidatorBuilder comes in is that we need a way to easily tell the Validator what list of rules it should operate on in a given scenario. Let’s walk through the example of a form with first name, email, and birth date.
Here is what we said the calling code will look like:
What’s happening here is as follows:
- Line 4 makes a call to new ValidatorBuilder(), which if you reference line 4 of the ValidatorBuilder class, creates the builder which in turn creates an empty Validator object to work on
- Line 5 calls “withBlankFieldValidation” which calls the corresponding method in ValidatorBuilder. This method creates the ValidationRule with logic to make sure that any String is not blank. It then adds that ValidationRule to the Validator contained in the ValidatorBuilder. Finally, it returns the ValidatorBuilder itself! This is what allows the “fluent” method of chaining method calls.
- Line 6 calls the “withEmailValidation” method, which follows the entirely same pattern as the withBlankFieldValidation method. Again, to maintain separation of concerns, the withEmailValidation method actually delegates this work to the Apache Commons Validator EmailValidator class.
- Repeat as often as you like! Here we don’t call any other “with_____” methods, but we totally could!
- Finally, “buildAndValidate” is called. This method doesn’t return a ValidatorBuilder, because it is always the last method in the chain. See lines 12-15 of ValidatorBuilder. All this does is call the Validator’s validate() method and then returns it.
I hope this is understandable. Please post any questions or use the contact form under the about menu.
As you can see, the Builder pattern simplifies things a lot. Instead of giving the Validator class a bunch of setters, or relying on multiple constructors, or constructors with a bunch of boolean flags or null values, you get a very clear way to create the Validator object. Basically you have separated out the concern of the Validator class (to validate things) from the concern of building a Validator instance, and everything becomes much clearer.
Here is the Validator class, so you can see how simple it is, as well:
What are the advantages?
The advantages are clear/easy client code, very flexible Validator creation using only one line, as well as a very maintainable piece of code for any future form validation needs. For example, we mentioned what if a phone number field was added to the code in the future.
What are the disadvantages?
The only disadvantage I see seems to be moving code out to another file or to an inner class down below. Some developers don’t like this because then they have to flip back and forth between windows or else scroll up and down to understand the context. On the other hand, I can assure everybody that once you’ve seen this pattern just a couple times it is immediately obvious. Since it has already been codified as a pattern in 1995 (that’s when Design Patterns came out) then I think its safe to say this is a common piece of our software engineering language. Everyone should learn it, and everyone should use it! Even if you don’t use it, you’ll come across it sooner or later.