2014-09-26 108 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

相關問題