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


      静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。

      当一个类中有若干个必选属性和多个可选属性时,采用重叠构造器模式、JavaBeans模式或者Builder模式,但各有优劣。

      当有很多参数的时候,重叠构造器模式下客户端代码会很难编写,并且仍然较难以阅读。

      JavaBeans模式调用一个无参构造器来创建对象,然后调用setter方法来设置每个必要的参数,以及每个相关的可选参数。因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。与此相关的另一点不足在于,JavaBeans模式阻止了把类做成不可变的可能。

      Builder模式不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象,然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数,客户端最后调用无参的build方法来生成不可变的对象。这个builder是它构建的类的静态成员类。

      下面就是它的示例:

     1 public class NutritionFacts {
     2     private final int servingSize;
     3     private final int servings;
     4     private final int calories;
     5     private final int fat;
     6     private final int sodium;
     7     private final int carbohydrate;
     8 
     9     public static class Builder {
    10         // Required parameters
    11         private final int servingSize;
    12         private final int servings;
    13 
    14         // Optional parameters - initialized to default values
    15         private int calories = 0;
    16         private int fat = 0;
    17         private int carbohydrate = 0;
    18         private int sodium = 0;
    19 
    20         public Builder(int servingSize, int servings) {
    21             this.servingSize = servingSize;
    22             this.servings = servings;
    23         }
    24 
    25         public Builder calories(int val) {
    26             calories = val;
    27             return this;
    28         }
    29         public Builder fat(int val) {
    30             fat = val;
    31             return this;
    32         }
    33         public Builder carbohydrate(int val) {
    34             carbohydrate = val;
    35             return this;
    36         }
    37         public Builder sodium(int val) {
    38             sodium = val;
    39             return this;
    40         }
    41 
    42         public NutritionFacts build() {
    43             return new NutritionFacts(this);
    44         }
    45     }
    46 
    47     private NutritionFacts(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 
    56     public static void main(String[] args) {
    57         NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
    58                 calories(100).sodium(35).carbohydrate(27).build();
    59     }
    60 }

     

      它在检验约束时将参数从builder拷贝到对象中之后,并在对象域而不是builder域中对它们进行检验。如果违反了任何约束条件,build方法就应该抛出IllegalArgumentException。对多个参数强加约束条件的另一个方法是,用多个setter方法对某个约束条件必须持有的所有参数进行检查。一旦传递了无效的参数,立即就会发现约束条件失败,而不是等着调用build方法。与构造器相比,builder的微略优势在于,builder可以有多个可变参数。构造器就像方法一样,只能有一个可变参数。

      Java中传统的抽象工厂实现是Class对象,newInstance方法总是企图调用类的无参构造器,这个构造器甚至可能根本不存在。Class.newInstance破坏了编译时的异常检查。Builder模式也存在不足。为了创建对象,必须先创建它的构建器。在十分注重性能的情况下,可能就成问题了。Builder模式还比重叠构造器模式更加冗长,因此它只在有很多参数的时候才使用,比如4个或者更多个参数。通常最好一开始就使用构建器。

      如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBeans更加安全。

     

      参考资料

      《Effective Java 中文版 第2版》 第2条:遇到多个构造器时要考虑用构建器 P9-13

  • 相关阅读:
    HDU 6071
    HDU 6073
    HDU 2124 Repair the Wall(贪心)
    HDU 2037 今年暑假不AC(贪心)
    HDU 1257 最少拦截系统(贪心)
    HDU 1789 Doing Homework again(贪心)
    HDU 1009 FatMouse' Trade(贪心)
    HDU 2216 Game III(BFS)
    HDU 1509 Windows Message Queue(队列)
    HDU 1081 To The Max(动态规划)
  • 原文地址:https://www.cnblogs.com/WJQ2017/p/7607193.html
Copyright © 2020-2023  润新知