假设我们在自己的包中有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
}
这被认为是安全和良好的设计吗?如果没有,为什么?
最佳答案 我的建议:
>将Builder放在用户中,所以它更简单
Builder构建和用户可以访问的私有字段
因此,构建器中不需要构造器.
>使用户构造函数为私有,因为受保护意味着派生类可以访问构造函数,因此不可变性可能会破坏.
>不需要getUser()方法.
这是我的例子:
public final class User {
private final String firstName, lastName;
private final int age;
private final String address;
private final List<User> friends;
private User(Builder builder) {
this.firstName = builder.lastName;
this.lastName = builder.lastName;
this.age = builder.age;
this.address = builder.address;
this.friends = Collections.unmodifiableList(new ArrayList<>(builder.friends)); //immutable list
}
public String getFirstName() {
return firstName;
}
public List<User> getFriends() {
return friends;
}
/**
* other getters;
*/
public static class Builder {
private String firstName, lastName;
private int age;
private String address;
private List<User> friends = new ArrayList<>();
public Builder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public Builder setAge(int age) {
this.age = age;
return this;
}
public Builder setAddress(String address) {
this.address = address;
return this;
}
public Builder addFriend(User friend) {
this.friends.add(friend);
return this;
}
public User build() {
return new User(Builder.this);
}
}
public static void main(String[] args) {
User johnSmith = new User.Builder("John", "Smith").setAge(33).setAddress("New York").build();
}
}