- The builder pattern, as name implies, is an alternative way to construct complex objects.
- A builder pattern is more like fluent interface. A fluent interface is normally implemented by using method cascading (or method chaining).
- Builder pattern aims to “Separate the construction of a complex object from its representation so that the same construction process can create different representations.”
A complete Java builder pattern example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | package albert.practice.designpattern.builder; import java.util.regex.Pattern; import lombok.Getter; import lombok.ToString; @Getter @ToString public class User { private final String firstName; private final String lastName; private final Integer age; private final String phone; private final String email; private User(UserBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.age = builder.age; this.phone = builder.phone; this.email = builder.email; } public static class UserBuilder { private String firstName; private String lastName; private Integer age; private String phone; private String email; public UserBuilder firstName(String firstName) { this.firstName = firstName; return this; } public UserBuilder lastName(String lastName) { this.lastName = lastName; return this; } public UserBuilder age(Integer age) { this.age = age; return this; } public UserBuilder phone(String phone) { this.phone = phone; return this; } public UserBuilder email(String email) { this.email = email; return this; } public User build() { User user = new User(this); // Do some basic validations to check if (!isEmailValid(user.getEmail())) { throw new RuntimeException(user.getEmail() + " is invalid Email format!"); } return user; } public Boolean isEmailValid(String email) { Boolean isValid = Boolean.FALSE; Pattern EMAIL_PATTERN = Pattern.compile("^\\w+\\.*\\w+@(\\w+\\.){1,5}[a-zA-Z]{2,3}$"); if (EMAIL_PATTERN.matcher(email).matches()) { isValid = Boolean.TRUE; } return isValid; } } } |
Example to use above builder pattern to create a User object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package albert.practice.designpattern.builder; import albert.practice.designpattern.builder.User.UserBuilder; import lombok.extern.slf4j.Slf4j; @Slf4j public class BuilderTest { public static void main(String[] args) { User albert = new UserBuilder() .lastName("Kuo") .firstName("Albert") .phone("1234567890") .age(30) .email("test@gmail.com") .build(); log.debug(" user1 = " + albert.toString()); User mandy = new UserBuilder() .lastName("Yeh") .firstName("Mandy") .email("yeh@gmail.com") .build(); log.debug(" user2 = " + mandy.toString()); } } |
Benefits and Advantages
- The number of lines of code increase at least to double in builder pattern, but the effort pays off in terms of design flexibility and much more readable code. The parameters to the constructor are reduced and are provided in highly readable method calls.
- The constructor is private, which means that this class can not be directly instantiated from the client code.
- The class is once again immutable. All attributes are final and they’re set on the constructor. Additionally, only provide getters for them.
- The builder uses the Fluent Interface idiom to make the client code more readable.
Conclusion
Using builder pattern for constructing objects when having a lot of parameters, especially if many of these parameters are null and when many of them share the same data type. A developer might feel that the extra code to implement a Builder might not justify its benefits for a small number of parameters, especially if the few parameters are required and of different types. In such cases, it might be considered desirable to use traditional constructors or, if immutability is not desired, use a no-argument constructor and require the client to know to call the necessary "set" methods.
Reference
[1] http://www.javaworld.com/article/2074938/core-java/too-many-parameters-in-java-methods-part-3-builder-pattern.html?page=2
[2] http://howtodoinjava.com/design-patterns/creational/builder-pattern-in-java/