2015-11-16 23 views
4

假设我们有UserUserBuilder类在自己的包,我们想成为不可改变的,在初始化之前一致的状态,定义如下:这是建造者模式的有效变体吗?

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     
    } 

这是否被认为是安全和良好的设计?如果不是,为什么?

回答

0

您正在检索不可变对象,所以这是正确的。但是你正在创建一个User对象,意识到这个构建器对象,我认为这是不对的,因为User类不需要知道有一个构建器类,所以你需要耦合这两个类,我的意思是,User直接依赖UserBuilder,没有UserBuilder用户不能编译,这是不是一个好的设计

我认为你将有以下的另一个问题的答案更好的设计,与这些示例,您将删除类耦合

0
  1. 将UserBuilder放置在用户内部

  2. 创建用户的构造函数,使用fi首先/最后的姓名,地址,年龄用户的私人

+0

我想避免嵌套的建设者,因为我觉得它会降低代码的可读性。我知道如果你有嵌套的构建器,你可以有私有构造器。 –

+1

然后选择默认的用户构造函数可见性,但不保护 – Nyavro

+0

但是,然后你可以通过调用User的构造函数并使用UserBuilder实例,可以或不可以完全初始化,这使得整个练习有Builder无意义。 –

0

保护的

  • 制作构造不仅在同一包访问,但在子类为好。 在User中包含Builder类作为嵌套类。 该方法描述为here

  • 1

    我的建议:

    • 放置BuilderUser里面,所以它更琐碎什么 Builder建立和用户可以访问 构建的私有字段,因此在不需要消气建设者。
    • 制作User构造函数private,因为protected意味着派生类可以访问构造函数,所以不变性可以打破。
    • 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(); 
        } 
    
    } 
    
    +1

    同一包中的类也可以访问'受保护的'成员。请参阅https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html –