遇到多个构造器参数时要考虑用构建器

     考虑用一个类表示包装食品外面显示的营养成分标签,这些标签中有几个域是必需的:每份的含量,每罐的含量以及每份的卡路里,还有一些可选域:钠,歆,铁,总脂肪含量等等!下面以四个可选域举例。

    一般大家习惯采用重叠构造器模式:

 1 public class NutritionFacts1 {
 2 
 3     private final int servingSize;
 4     private final int servings;
 5     private final int calories;
 6     private final int fat;
 7     private final int sodium;
 8     private final int carbohydrate;
 9     
10     public NutritionFacts1(int servingSize,int servings){
11         this(servingSize,servings,0);
12     }
13     
14     public NutritionFacts1(int servingSize,int servings,int calories){
15         this(servingSize,servings,calories,0);
16     }
17     
18     public NutritionFacts1(int servingSize,int servings,int calories,int fat){
19         this(servingSize,servings,calories,fat,0);
20     }
21     
22     public NutritionFacts1(int servingSize,int servings,int calories,int fat,int sodium){
23         this(servingSize,servings,calories,fat,sodium,0);
24     }
25     
26     public NutritionFacts1(int servingSize,int servings,
27             int calories,int fat,int sodium,int carbohydrate){
28         this.servingSize=servingSize;
29         this.servings=servings;
30         this.calories=calories;
31         this.fat=fat;
32         this.sodium=sodium;
33         this.carbohydrate=carbohydrate;
34     }
35     
36 }
 1 public class BuilderTest {
 2 
 3     public static void main(String[] args) {
 4 
 5         NutritionFacts1 nf1 = new NutritionFacts1(240,8,100,0,35,27);
 6         System.out.println(nf1.toString());
 7     
 8     }
 9 
10 }

这仅仅是6个参数,一旦参数增加,问题就来了!客户端代码会很难写,并且比较难以阅读!

     第二种方法是JavaBeans模式:

 1 public class NutritionFacts2 {
 2 
 3     private  int servingSize = -1;
 4     private  int servings = -1;
 5     private  int calories = 0;
 6     private  int fat = 0;
 7     private  int sodium = 0;
 8     private  int carbohydrate = 0;
 9     
10     public NutritionFacts2(){}
11     
12     public void setServingSize(int servingSize){
13         this.servingSize = servingSize;
14     }
15     public void setServings(int servings){
16         this.servings = servings;
17     }
18     public void setCalories(int calories){
19         this.calories = calories;
20     }
21     public void setFat(int fat){
22         this.fat = fat;
23     }
24     public void setSodium(int sodium){
25         this.sodium = sodium;
26     }
27     public void setCarbohydrate(int carbohydrate){
28         this.carbohydrate = carbohydrate;
29     }
30     
31 }
 1 public class BuilderTest {
 2 
 3     public static void main(String[] args) {
 4 
 5         NutritionFacts2 nf2 = new NutritionFacts2();
 6         nf2.setServingSize(10);
 7         nf2.setServings(20);
 8         nf2.setCalories(1);
 9         nf2.setCarbohydrate(5);
10         nf2.setFat(0);
11         nf2.setSodium(10);
12     
13     }
14 
15 }

 

JavaBeans模式的缺点:

                            1,构造的过程分到了几个调用中,在构造JavaBeans的时候可能会不一致。

                            2,类无法仅仅通过检验构造器参数的有效性来保证一致性!

                            3,对象的不一致会导致失败,JavaBeans模式阻止了把类做为不可变的可能,需要程序员做额外努力来保证它线程安全。

但是大部分的时候JavaBean是在线程中new出来的,只会供单线程使用,很少会出现多个线程共享JavaBean的情况!

      第三种方法Builder模式,既保证了像重叠构造器模式那样的安全,也能保证像JavaBeans模式那么好的可读性!

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

 

posted @ 2017-06-08 11:09  java白丁  阅读(310)  评论(0编辑  收藏  举报