美文网首页Java学习笔记系列
Effective Java Item 2 - 构造器

Effective Java Item 2 - 构造器

作者: SonyaBaby | 来源:发表于2018-02-05 23:35 被阅读0次

    在刚接触C++和Java时候,都会先学到构造器,用的多就习惯了重叠式构造器方式,但是当参数很多的时候就会diss存值的顺序,推荐使用builder,下面还是用书中的例子作说明

    public class Item2_Builder {
    
      private final int servingSize;
      private final int servings;
      private final int calories;
      private final int fat;
      private final int sodium;
      private final int carbohydrate;
    
      public static class Builder{ //类内部构造器
        // required
        private final int servingSize;
        private final int servings;
        // optional
        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbohydrate = 0;
    
        public Builder ( int servingSize, int servings){//必要的参数
          this.servings = servings ;
          this.servingSize = servingSize;
        }
        public Builder fat(int val){//可选填的参数
          this.fat = fat;
          return this;
        }
        public Builder sodium(int val){//可选填的参数
          this.sodium = sodium;
          return this;
        }
        public Builder calories(int val){//可选填的参数
          this.calories = calories;
          return this;
        }
        public Builder carbohydrate(int val){//可选填的参数
          this.carbohydrate = carbohydrate;
          return this;
        }
    
        public Item2_Builder build(){//将Builder的值[复制]给Item2_Builder
          return new Item2_Builder(this);
        }
      }
    
      private Item2_Builder(Builder builder){//将Builder的值[复制]给Item2_Builder
        calories = builder.calories;
        servingSize = builder.servingSize;
        servings = builder.servings;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
      }
    

    我们在调用时候可以这样使用

    public static void main(String[] args) {
      Item2_Builder cocaCola = new Item2_Builder.Builder(100,10).calories(100).fat(50).sodium(60)
    .build();
      }
    }
    

    Builder相对于setter方式,好处自然也很明显啦,不需要重复的写A.set,可以串成链式。

    A.set(B);
    A.set(C);
    A.set(D);
    A.set(E);
    

    Builder模式模拟了具名的可选参数,就像Ada和Python中的一样。

    builder可以对多参数加约束条件:

    • 第一种是build()方法,在进行值的复制时候,是在对象域中进行的校验。违反了就会抛出IllegalStateException
    • 第二种是用多个setter方法对某个约束条件必须持有的参数进行检查,若不满足,则抛出IllegalArgumentException,即一旦传了无效的参数,立刻会发现约束条件失败,而不是在build方法时才检查。

    Builder相比构造器的优点:

    • builder可以有多个可变参数,想要多少个就有多少个
    • 若类的构造器或者静态工厂中具有多个参数,设计时Builder更易阅读和编写
    • 若遇到在之后的开发中可能会新增参数,Builder更易拓展,前期使用构造器或静态工厂,到后期进行结构调整会无法控制

    Builder 不足之处

    • 为了创建对象,必须先构建构建器
    • Builder模式比重叠构造器还咬冗长,所以是很多参数的时候才使用

    抽象工厂Builder<T>

    public interface Builder<T>{
        public T builder();
     }
    

    eg:
    Item2_Builder.Builder()类可以实现Builder<Item2_Builder>

    注意:
    传统的抽象工厂实现的是Class对象,用newInstance来充当build会隐藏一些问题:
    newInstance总是企图调用类的无参构造器,这个构造器可能根部不存在,如果类没有可以访问的无参构造器,编译时也不会报错。在运行时将会报错:InstantiationException或者IllegalAccessException
    即newInstance缺乏响应的throws子句,换句话说Class.newInstance破坏了编译时的异常检查。Builder接口弥补了这些。

    相关文章

      网友评论

        本文标题:Effective Java Item 2 - 构造器

        本文链接:https://www.haomeiwen.com/subject/nrfwzxtx.html