Переход от JavaBeans к шаблону Builder
Я использую Retrofit в своем приложении, у меня есть классы POJO, которые я использую, чтобы сделать запрос и проанализировать ответ. В настоящее время я использую шаблон JavaBeans и имею методы получения и установки для всех переменных в классе для всех классов POJO.
Вот мой класс пользователя, например
public class User {
@SerializedName("user_name")
private String userName;
@SerializedName("password")
private String userPassword;
@SerializedName("address_info")
private AddressInfo AddressInfo;
@SerializedName("contact_info")
private ContactInfo ContactInfo;
/*
*@return The userName
*/
public String getUserName() {
return userName;
}
/**
* @param userName The userName
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* @return The userPassword
*/
public String getPassword() {
return userPassword;
}
/**
* @param userPassword The userPassword
*/
public void setPassword(String userPassword) {
this.userPassword = userPassword;
}
/// so on for the AddressInfo and ContactInfo
}
Это работает хорошо. Я пытаюсь использовать шаблон компоновщика вместо шаблона JavaBeans.
Я изменил свой класс пользователя на:
public class User {
@SerializedName("user_name")
private String userName;
@SerializedName("password")
private String userPassword;
@SerializedName("address_info")
private AddressInfo AddressInfo;
@SerializedName("contact_info")
private ContactInfo ContactInfo;
public static class UserBuilder {
private String userName;
private String userPassword;
private AddressInfo AddressInfo;
private ContactInfo ContactInfo;
//builder methods for setting property
public UserBuilder userName(String user_name) {
this.userName = user_name;
return this;
}
public UserBuilder userPassword(String user_password) {
this.userPassword = user_password;
return this;
}
public UserBuilder AddressInfo(AddressInfo addressInfo) {
this.AddressInfo = addressInfo;
return this;
}
public UserBuilder ContactInfo(ContactInfo contactInfo) {
this.ContactInfo = contactInfo;
return this;
}
//return fully build object
public User build() {
return new User(this);
}
}
//private constructor to enforce object creation through builder
private User(UserBuilder builder) {
this.userName = builder.userName;
this.userPassword = builder.userPassword;
this.AddressInfo = builder.AddressInfo;
this.ContactInfo = builder.ContactInfo;
}
//Getters for userName,userPassword,AddressInfo and ContactInfo
}
Класс AddressInfo
public class AddressInfo {
@SerializedName("address_1")
private String address1;
@SerializedName("city")
private String city;
@SerializedName("state")
private String state;
@SerializedName("zip_code")
private String zipCode;
/**
* @return The address1
*/
public String getAddress1() {
return address1;
}
/**
* @return The city
*/
public String getCity() {
return city;
}
/**
* @return The state
*/
public String getState() {
return state;
}
/**
* @return The zip code
*/
public String getZipCode() {
return zipCode;
}
}
Вопрос: 1. Я удалил сеттеры из классов POJO AddressInfo и ContactInfo. Нужно ли реализовывать шаблон построителя в классах AddressInfo и ContactInfo? Вот как работает шаблон.
Как я могу добиться этого:
User user = new User.UserBuilder().userName("test").userPassword("******").address("100 Townsend St").city("San Francisco").zip("94107").build();
2 ответа
С
User user = new User.UserBuilder().userName("test")
.userPassword("******").address("100 Townsend St")
.city("San Francisco").zip("94107").build();
Вы будете смешивать вещи. UserBuildr
должен нести ответственность за создание пользователя с использованием его адреса / контактной информации, а не за его создание. Вы должны иметь геттеры и сеттеры для экземпляров AddressInfo
а также ContactInfo
в User
класс, а также есть методы для их установки в UserBuilder
, Создайте строителя для каждого из них и используйте их следующим образом.
User user = new User.UserBuilder().userName("test")
.userPassword("******").addressInfo.(new AdressInfo.Builder()
.address1("100 Townsend St")
.city("San Francisco").zip("94107").build()).build();
Сделать то же самое для ContactInfo
,
Если вы не хотите, чтобы сеттеры AddressInfo
а также ContactInfo
чтобы быть доступным извне, вы можете сделать их защищенными, строитель все равно сможет получить к ним доступ, поскольку это внутренний класс.
Вы можете реализовать его для всех ваших классов, включая AddressInfo и ContactInfo. Идея этого шаблона - получить контроль над процессом создания объектов и избежать ситуаций, когда ваши объекты могут существовать в неправильном состоянии (например, пользователи без имени и фамилии). Это можно сделать, добавив этап проверки перед созданием объекта.
Вы можете реализовать это так, как показано ниже:
static class Inner { String innerValue; static class Builder { String innerValue; Builder innerVal(final String innerValue) { this.innerValue = innerValue; return this; } Inner build() { Inner inner = new Inner(); inner.innerValue = this.innerValue; return inner; } } } static class Outer { String outerValue; Inner inner; static class Builder { Inner.Builder innerBuilder; String outerValue; Builder() { this.innerBuilder = new Inner.Builder(); } Builder outerVal(final String outerValue) { this.outerValue = outerValue; return this; } Builder innerVal(final String innerValue) { this.innerBuilder.innerVal(innerValue); return this; } Outer build() { Outer outer = new Outer(); outer.outerValue = this.outerValue; outer.inner = this.innerBuilder.build(); return outer; } } }
Использование:
final Outer outer = (new Outer.Builder())
.innerVal("innerValue")
.outerVal("outerValue")
.build();
Но лично я пытаюсь разделить строителей на разные классы, так как это упрощает дизайн.