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


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

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

     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 }
  • 相关阅读:
    Spring创建对象的方法
    Spring学习笔记1
    WIN7系统TortoiseSVN右键没有菜单解决办法
    TotoiseSVN的基本使用方法
    sql语句中where 1=1和 0=1 的作用
    windows批处理命令教程
    Mysql之B树索引
    Mysql与索引有关的树的概念
    Mysql索引简介
    Mysql之explain详解
  • 原文地址:https://www.cnblogs.com/sqy123/p/6961786.html
Copyright © 2020-2023  润新知