Java構造器與構建器的使用


我們在平常類的構建過程中,可能會面臨很多問題,可擴張性、安全性等等。想象一下,這樣一個場景,我們現在要創建一個類,其中有6個屬性,其中又有4個屬性的值是不太確定的(可能某個對象就不需要其中的某個值),這時我們怎么創建這個類呢?以下是幾種方法:

使用普通構造器

 1 public class Test {
 2     private int servingSize;
 3     private int servings;
 4     private int calories;
 5     private int fat;
 6     private int sodium;
 7     private int carbohydrate;
 8 
 9     public Test(int servingSize, int servings) {
10         this.servingSize = servingSize;
11         this.servings = servings;
12         this.calories = 0;
13     }
14 
15     public Test(int servingSize, int servings, int calories) {
16         this.servingSize = servingSize;
17         this.servings = servings;
18         this.calories = calories;
19         this.fat = 0;
20     }
21 
22     public Test(int servingSize, int servings, int calories, int fat) {
23         this.servingSize = servingSize;
24         this.servings = servings;
25         this.calories = calories;
26         this.fat = fat;
27         this.sodium = 0;
28     }
29 
30     public Test(int servingSize, int servings, int calories, int fat, int sodium) {
31         this.servingSize = servingSize;
32         this.servings = servings;
33         this.calories = calories;
34         this.fat = fat;
35         this.sodium = sodium;
36         this.carbohydrate = 0;
37     }
38 
39     public Test(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
40         this.servingSize = servingSize;
41         this.servings = servings;
42         this.calories = calories;
43         this.fat = fat;
44         this.sodium = sodium;
45         this.carbohydrate = carbohydrate;
46     }
47 
48 }

我們完成該類構建后,接下來就是調用的過程:

1 public static void main(String[] args) {
2         Test test = new Test(1,2,3,0,5,6);
3 }

如上所示,在實例化對象時,我們需要傳入相應的值,這時發現:

  1. 第四個參數不是我們需要的,但是還不得不給他傳遞一個值
  2. 我們在傳值時,很容易出錯,某兩個參數值互換了位置,這在工作時是不好發現的,但是程序會報錯

所以上面的方式在涉及到參數比較多,而且參數值不太確定是否需要時,這種方法會給我們的編碼以及后期維護帶來很大的困擾,我們再改進一下。

JavaBeans模式

 1 public class Test {
 2     private int servingSize;
 3     private int servings;
 4     private int calories;
 5     private int fat;
 6     private int sodium;
 7     private int carbohydrate;
 8 
 9     public Test() {
10 
11     }
12 
13     public void setServingSize(int servingSize) {
14         this.servingSize = servingSize;
15     }
16 
17     public void setServings(int servings) {
18         this.servings = servings;
19     }
20 
21     public void setCalories(int calories) {
22         this.calories = calories;
23     }
24 
25     public void setFat(int fat) {
26         this.fat = fat;
27     }
28 
29     public void setSodium(int sodium) {
30         this.sodium = sodium;
31     }
32 
33     public void setCarbohydrate(int carbohydrate) {
34         this.carbohydrate = carbohydrate;
35     }
36 
37 
38 }

如上,我們先創建一個無參構造方法(可以不寫出來,會默認創建),接下來就是利用setter方法給屬性賦值

1 public static void main(String[] args) {
2         Test test = new Test();
3         test.setServingSize(1);
4         test.setCalories(2);
5         test.setCalories(3);
6         test.setSodium(5);
7         test.setCarbohydrate(6);
8 }

如上,我們需要的對象不需要fat屬性,我們就不用給其賦值,這中方法有幾個好處:

  1. 客戶端調用簡單,也就是實例化對象的過程十分簡單,並且不會出現把值傳遞出錯的風險
  2. 別人能夠很好的使用且理解簡單

但是我們知道,javaBeans有個缺點:

  1. 線程不安全,因為對象的創建分在了好幾步的過程中,不能保證對象狀態的一致性

我們可以確保線程的安全,這就需要我們額外的精力(我們可以在對象構造完成,並且不允許在凍結之前使用時,手動凍結,實際中很少使用,編譯器無法確定我們是否調用的freeze方法
。因此這種方法也不夠理想,還有什么繼續改進的地方嗎?

構建器(建造者模式的一種形式)

 1 public class Test {
 2     private int servingSize;
 3     private int servings;
 4     private int calories;
 5     private int fat;
 6     private int sodium;
 7     private int carbohydrate;
 8     
 9     public static class Builder {
10         private int servingSize;
11         private int servings;
12         private int calories;
13         private int fat;
14         private int sodium;
15         private int carbohydrate;
16         
17         public Builder (int servingSize, int servings) {
18             this.servingSize = servingSize;
19             this.servings = servings;
20         }
21         
22         public Builder calories(int calories) {
23             calories = calories;
24             return this;
25         }
26 
27         public Builder fat(int fat) {
28             fat = fat;
29             return this;
30         }
31 
32         public Builder sodium(int sodium) {
33             sodium = sodium;
34             return this;
35         }
36 
37         public Builder carbohydrate(int carbohydrate) {
38             carbohydrate = carbohydrate;
39             return this;
40         }
41         
42         public Test builder () {
43             return new Test(this);
44         }
45     }
46     
47     private Test(Builder builder) {
48         servingSize = builder.servingSize;
49         servings = builder.servings;
50         calories = builder.calories;
51         fat = builder.fat;
52         sodium = builder.sodium;
53         carbohydrate = builder.carbohydrate;
54     }
55 }

調用方式:

1 public static void main(String[] args) {
2         Test test = new Builder(1,2).calories(3).fat(4).sodium(5).carbohydrate(6).builder();
3}

這樣就保證了對象在不變的情況下,簡單明了地實現了對象實例化(至於代碼中的內部類,我們以后細說)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM