2017-06-07 95 views
4

所以當我編寫自己的項目時,初始化一個對象時出現了一個問題。我的班級有很多屬性需要啓動,但並不總是全部都是這樣。這時候,我想出了這個主意(但我不知道這是否是之前的任何地方使用):建議這種初始化方法嗎?

public class MyClass { 
    public static final int DEFAULT1 = 1; 
    public static final int DEFAULT2 = 2; 
    public static final int DEFAULT3 = 3; 
    private int attr1; 
    private int attr2; 
    private int attr3; 
    private MyClass(){ 
     attr1 = DEFAULT1; 
     attr2 = DEFAULT2; 
     attr3 = DEFAULT3; 
    } 
    public static MyClass create(){ 
     return new MyClass(); 
    } 
    public MyClass setAttr1(int attr1){ 
     this.attr1 = attr1; 
     return this; 
    } 
    public MyClass setAttr2(int attr2){ 
     this.attr2 = attr2; 
     return this; 
    } 
    public MyClass setAttr3(int attr3){ 
     this.attr3 = attr3; 
     return this; 
    } 
} 

當我創建一個新的MyClass比如我會做:

MyClass obj = MyClass.create().setAttr1(3).setAttr3(1); 

它工作了我(有些是因爲我測試過,但我還沒有決定在我的項目中使用它)。我的問題是,這是合法的嗎?它會產生任何種類的內存/執行問題嗎?

+2

使用製造商的設計模式,如果你有一些可選的屬性更多https://www.tutorialspoint.com/design_pattern/builder_pattern.htm,這是創建對象的推薦方式,它特別適合您的情況。 –

+0

哦,對,謝謝你指出。我不知道這個哈哈有一個完整的設計模式。 –

+2

這已經非常接近Builder的設計模式了,正如上面的@AmitK所討論的那樣。爲了實現這一目標,將'setAttr *'方法移出到另一個名爲「MyClassBuilder」的類,它們將返回當前的「MyClassBuilder」對象以幫助鏈接。最後,應該有一個實例方法'build',它創建一個MyClass對象,並設置屬性並將其返回(您可能希望將這些類放入一個單獨的包中,併爲您的字段使用包 - 私有(默認)可見性如有必要)。 –

回答

7

您的使用案例是Builder設計模式的完美示例。詳細瞭解​​和oracle doc about builder。另請閱讀爲什麼Builder模式與Java傳奇Joshua的其他創作模式相比具有優勢,這是在他的書中討論的,其最佳實踐是java here

使用Builder設計模式的轉換後的類將如下所示。請注意,我假設爲attr1可選,並且attr2attr3爲必填項。

class MyClass { 
    public static final int DEFAULT1 = 1; 
    public static final int DEFAULT2 = 2; 
    public static final int DEFAULT3 = 3; 

    // assume attr1 is optional 
    private int attr1; 
    // assume attr2,3 is mandatory 
    private int attr2; 
    private int attr3; 


    public MyClass(MyClassBuilder myClassBuilder) { 
     this.attr1 = myClassBuilder.attr1; 
     this.attr2 = myClassBuilder.attr2; 
     this.attr3 = myClassBuilder.attr3; 
    } 

    //Builder Class 
    public static class MyClassBuilder { 

     // required parameters 
     private int attr2; 
     private int attr3; 
     // optional parameters 
     private int attr1; 

     public MyClassBuilder(int attr2, int attr3){ 
      this.attr2 = attr2; 
      this.attr3 = attr3; 
     } 

     public MyClassBuilder setAttr1(int attr1) { 
      this.attr1 = attr1; 
      return this; 
     } 


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

    } 

} 

現在,使用下面的代碼之後,您可以創建對象(帶/不帶)可選參數。其中

public class MyClassTest { 

    public static void main(String[] args) { 
     MyClass myClass = new MyClass.MyClassBuilder(10,20).build(); 
    // without optional param 
    System.out.println("without optional param"); 
    System.out.println("attr1 "+ myClass.getAttr1()); 
    System.out.println("attr2 "+ myClass.getAttr2()); 
    System.out.println("attr3 "+ myClass.getAttr3()); 

    // with optional param 
    System.out.println("with optional param"); 
    MyClass myClassWithAllParam = new MyClass.MyClassBuilder(10,20).setAttr1(5).build(); 
    System.out.println("attr1 "+ myClassWithAllParam.getAttr1()); 
    System.out.println("attr2 "+ myClassWithAllParam.getAttr2()); 
    System.out.println("attr3 "+ myClassWithAllParam.getAttr3()); 

    } 
} 

輸出如下: -

without optional param 
attr1 0 
attr2 10 
attr3 20 
with optional param 
attr1 5 
attr2 10 
attr3 20 
+0

非常具體的例子。非常感謝你:) –

+0

@DatHuynh,如果你喜歡我的回答,請不要忘記接受並投票回答:)。 –

2

它的另一個名字是Fluent Interface

您只需要使用with而不是set作爲方法名稱。 set命名是爲JavaBeans約定保留的。