2014-09-26 75 views
2

在构建器中声明父类的实例并使用该变量初始化每个Field并在构建器中再次分别声明每个变量,然后声明构建器作为构造器的一部分来初始化每个Field有什么区别?这些构建器模式之间有什么区别?

public class Foo { 

    public int i; 
    public String s; 

    private Foo(Builder builder) { 
     i = builder.i; 
     s = builder.s; 
    } 

    public static class Builder { 

     private int i; 
     private String s; 

     public Builder i(int i) { 
      this.i = i; 
      return this; 
     } 

     public Builder s(String s) { 
      this.s = s; 
      return this; 
     } 

     public Foo build() { 
      return new Foo(this); 
     } 
    } 

} 

public class Foo { 

    public int i; 
    public String s; 

    public static class Builder { 

     private final Foo mFoo = new Foo(); 

     public Builder i(int i) { 
      mFoo.i = i; 
      return this; 
     } 

     public Builder s(String s) { 
      mFoo.s = s; 
      return this; 
     } 

     public Foo build() { 
      return mFoo; 
     } 
    } 

} 

回答

5

第一种方法是规范的一个。

在我看来,第二种方法的主要限制是:

  • 你不能做的Foo(对象你正在构建)final成员,因为他们施工后分配。
  • 您必须在正在构建的类中声明构建器,以便它可以访问私有成员或设置器,或者声明非私有成员或设置器方法,以便构建器可以访问它们,即使该级别的访问可能不适合后建设。
  • 正在建设中的对象Foo会经历几种不同的状态,这些状态可能无效。根据您使用何种方法以此增量方式构造对象,您可能会限制您可以执行的验证。通常的构建器模式会收集要构建的对象的所有状态,然后构建它,从而允许构造器对最终状态执行所有必要的验证。
  • 构建器不能构建多个对象。在通常的构建器模式中,您可以多次调用build()来构建多个对象,可能会与对构建器方法的调用交错以修改后续对象。

我可以看到第二种方法的唯一真正好处是您可以节省一些样板 - 您不必重新声明构建器对象中的成员,并且可能具有更好的性能,因为值不会必须从Builder中复制到最终对象。

+0

删除该样板是我甚至考虑第二个的唯一原因。我的类包含了很多变量,并且有一个100多行代码大部分来自setter的代码,这有点让人讨厌。 – user4081847 2014-09-26 03:44:02

相关问题