Witam. Ostatnio interesowałem się tematem fluent buildera. Z tego co zrozumiałem przy wielu polach dla danego obiektu pojawia się problem. Jeśli będziemy chcieli je wszystkie ustawiać w konstruktorze, to konstruktor będzie nieczytelny. Z kolei jeśli będziemy chcieli ustawiać pola przez settery to możemy o jakichś zapomnieć i stworzyć obiekt z niezadeklarowanymi wartościami dla pól. Nie rozumiem za bardzo jednak jak fluent builder rozwiązuje ten drugi problem. Jeśli stworzę sobie klasę:
public class Person {
private String name;
private String surname;
private int age;
private Person(){}
public String toString()
{
return "name: "+name+" surname: "+surname+" age: "+age;
}
public static final class Builder{
private String name;
private String surname;
private int age;
public Builder name (String name){
this.name = name;
return this;
}
public Builder surname (String surname){
this.surname = surname;
return this;
}
public Builder age (int age){
this.age = age;
return this;
}
public Person build(){
Person person = new Person();
person.name=name;
person.surname=surname;
person.age=age;
return person;
}
}
}
Tworząc obiekt cały czas mogę ominąć ustawianie poszczególnych pól. Jeśli byłoby ich trzykrotnie więcej łatwo o tym po prostu zapomnieć, tak jak przy ustawianiu przez settery. Pobrałem parę projektów z GitHuba i w zasadzie w większości wygląda to tak samo. Raz widziałem żeby w tworzonym obiekcie były pola obowiązkowe i opcjonalne:
public final class Email {
// To Address. Multiple Address separated by ","
String to;
//From Address
String from;
// Subject of the email
String subject;
// Content of the email
String content;
// BCC optional
String bcc;
// CC Optional
String cc;
/**
* Private constructor to prevent the object initialization
*/
private Email(String to, String from, String subject, String content, String bcc, String cc) {
this.to = to;
this.from = from;
this.subject = subject;
this.content = content;
this.bcc = bcc;
this.cc = cc;
}
public String getTo() {
return to;
}
public String getFrom() {
return from;
}
public String getSubject() {
return subject;
}
public String getContent() {
return content;
}
public String getBcc() {
return bcc;
}
public String getCc() {
return cc;
}
@Override
public String toString() {
return "Email{" +
"to='" + to + '\'' +
", from='" + from + '\'' +
", subject='" + subject + '\'' +
", content='" + content + '\'' +
", bcc='" + bcc + '\'' +
", cc='" + cc + '\'' +
'}';
}
// Interface to Set From
interface EmailFrom {
EmailTo setFrom(String from);
}
//Interface to Set To
interface EmailTo {
EmailSubject setTo(String to);
}
//Interface to Set subject
interface EmailSubject {
EmailContent setSubject(String subject);
}
// Interface to set Content
interface EmailContent {
EmailCreator setContent(String content);
}
// Final Email Creator Class
interface EmailCreator {
EmailCreator setBCC(String bcc);
EmailCreator setCC(String cc);
Email build();
}
/** Static class for building the email object
*/
public static class EmailBuilder implements EmailFrom, EmailTo, EmailSubject, EmailContent, EmailCreator{
String to;
String from;
String subject;
String content;
String bcc;
String cc;
/**
* Private emailbuilder to prevent direct object creation
*/
private EmailBuilder(){
}
/**
* Getting the instance method
* @return
*/
public static EmailFrom getInstance(){
return new EmailBuilder();
}
@Override
public EmailTo setFrom(String from) {
this.from = from;
return this;
}
@Override
public EmailSubject setTo(String to) {
this.to = to;
return this;
}
@Override
public EmailContent setSubject(String subject) {
this.subject=subject;
return this;
}
@Override
public EmailCreator setContent(String content) {
this.content=content;
return this;
}
@Override
public EmailBuilder setBCC(String bcc) {
this.bcc=bcc;
return this;
}
@Override
public EmailBuilder setCC(String cc) {
this.cc =cc;
return this;
}
@Override
public Email build() {
return new Email(to,from,subject,content,bcc, cc);
}
}
}
Tylko nie bardzo wiem czy to jest warte zachodu. Po mojemu traci na tym wszystkim czytelność. Czy przypadkiem nie jest tak, że bardziej w tych fluent builderach chodzi o to, żeby z jednej strony konstruktor nie był za duży, a z drugiej żeby nie było setterów po to by osiągnąć niemutowalność?