At First Sight of Builder Pattern

The first time I encountered the Builder Pattern would date back to the beautiful internship time in Red Hat. What inspired me a lot is its strange setter way.

 1 class PeopleBuilder {
 2     private String name = "Joseph"
 3     private int age = 24;
 4     private String talent = "programming";
 5 
 6     public PeopleBuilder setName(String name) {
 7  this.name = name;
 8  return this;
 9     }
10     public PeopleBuilder setAge(int age) {
11         this.age = age;
12  return this;
13     }
14     public PeopleBuilder setTalent(String talent) {
15  this.talent = talent;
16  return this;
17     }
18 }

The function will return object itself, in setter methods. Also these setter methods can avoid too many parameters in a function invocation process, such as:

 1     PeopleBuilder peopleBuilder = new PeopleBuilder();
 2     /*
 3      * Common definition for the doWork() function:
 4      */
 5     public void doWork(String workName, int age, String talent) {
 6  if(age < 18) {
 7      log.error("Can not employee cirtical labour!");
 8      throw new IllegalAgeException("age litter than 18");
 9         }
10  doTalent(talent);
11         log.info(String.format("Name:[%s], Talent:[%s]", workName, talent));
12     }
13     /*
14      * define function with PeopleBuilder object as the only parameters.
15      */
16     public void doWork(peopleBuilder.setAge(19).setName("Heng")
17  .setTalent("programming")) {
18  if(peopleBuilder.getAge() < 18) {
19      log.error("Can not employee cirtical labour!");
20      throw new IllegalAgeException("age litter than 18");
21         }
22  doTalent(peopleBuilder.getTalent());
23  log.info(String.format("Name:[$s], Talent:[%s]", peopleBuilder.getName()
24      , peopleBuilder.getTalent());
25     }

At the first glance of the above Builder Pattern usage, it resoved the too many parameters problem. However, when doWork() function invoke the PeopleBuilder class, it looks really strange and weild. Now the PeopleBuilder looks more like a POJO but a Builder. The get methods in Builder really strange. So the most important thing to do is to just figure out what the adventages and disadvantages do the builder pattern suit: 1. if you find that there are too many parameters in a function invocation, you could take a consideration: could it be encapsulated into a Java Bean Object. and with necessary *get, ***set* methods. 2. *Still, you find that the encapsulated class could not satify with your requirement. some construct parameters are necessary for you and some a optional. But all they could only be assigned value at first construct stage of the object. The object become read only, and be immutable. 3. Then, Builder Pattern is becoming your first choice.

An Example of Classical Builder Pattern.

mail sender builder

 1     Class EmailSender {
 2  /*
 3      * required parameters for send a email.
 4      */
 5  private final String subject;
 6  private final String from;
 7  private final String to;
 8  /*
 9      * optional parameters.
10      */
11  private final String cc;
12  private final String body;
13 
14  /*
15      * private construct function with EmailSenderBuilder.
16      */
17  private EmailSender(EmailSenderBuilder emailBuilder) {
18      this.subject = emailBuilder.subject;
19      this.from = emailBuilder.from;
20      this.to = emailBuilder.to;
21      this.cc = emailBuilder.cc;
22      this.body = emailBuilder.body;
23  }
24  /**
25      * noted the static class accessor.
26      */
27       public static EmailSenderBuilder {
28           private final String subject;
29           private final String from;
30           private final String to;
31           private String cc;   /* non-final statement compared to EmailSender */
32           private String body; /* non-final statement compred to EmailSender */
33           public EmailSenderBuilder(String subject, String from, String to) {
34               this.subject = subject;
35               this.from = from;
36               this.to = to;
37       }
38           /**
39           * fluent interface idiom .
40           */
41           public subject(String subject) {
42               this.subject = subject;
43               return this;
44           }
45           public from(String from) {
46               this.from = from;
47               return this;
48           }
49           public to(String to) {
50               this.to = to;
51               return this;
52           }
53           /**
54           * It's definitely cool! Also you can implement the logic
55           * condition in build according to your requirement.
56           */
57           public EmailSender build() {
58               return new EmailSender(this);
59           }
60       }
61     }

So long and thanks for all the fish!

Reference