Давайте предположим, что мы имеем User
и UserBuilder
класса в своем собственном пакете, что мы хотим быть неизменны и в целостном состоянии до инициализации, определяется следующим образом:Является ли этот допустимый вариант шаблона строителя?
public class User {
private final String firstName, lastName;
private final int age;
private final String adress;
protected User(UserBuilder buildUser) { //constructor acessible only in same packge
this.firstName = buildUser.lastName;
this.lastName = buildUser.lastName;
this.age = buildUser.age;
this.adress = buildUser.adress;
}
public String getFirstName() {
return firstName;
}
... // and other getters
}
А класс строитель следующим образом:
public class UserBuilder {
public final String firstName;
public final String lastName;
public int age;
public String adress;
public UserBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public UserBuilder setAge(int age) {
this.age = age;
return this;
}
public UserBuilder setAdress(String adress) {
this.adress = adress;
return this;
}
public UserBuilder getUser() {
return this;
}
public User build() {
return new User(getUser());
}
}
И, наконец, мы строим пользователю в классе, который находится в другом пакете:
public static void main(String[] args) {
User user = new UserBuilder("John","Doe")
.setAge(22)
.build();
// User user = new User(UserBuilder) //error protected constructor
}
Это считается безопасным и хорошим дизайном? Если нет, то почему?
Я хотел избежать вложенного строителя, потому что я считаю, что ухудшает читаемость кода. Я знаю, если у вас есть вложенный конструктор, вы можете иметь частный конструктор. –
Затем выберите видимость конструктора по умолчанию, не защищенную – Nyavro
Но тогда вы можете передать UserBuilder внутри конструктора User в несогласованном состоянии, вызвав конструктор пользователя и используя экземпляр UserBuilder, который может быть или не быть полностью инициализирован, что делает все упражнение с Builder бессмысленно. –