第二条:遇到多个构造器参数时要考虑用构建器

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

假如一份营养成分的标签,有两个域是必须的,四个域是可选的。

1.重叠构造器模式

提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个构造器有两个可选参数,依次类推,直到最后一个构造器包含所有的可选参数。

缺点:谁作为第一个可选参数是一个问题,因为后一个包含两个可选参数的构造器必须传递值给第一个可选参数,导致需要设置许多本不想设置的参数,像是一个极端的例子NutritionFacts n = new NutritionFacts(240,8,0,0,0,10),只有最后一个可选参数是我们想设置的,然而之前的三个可选参数我们也不得不设置。

2.JavaBean模式

通过一个无参构造器创建对象,然后调用setter方法来设置每个必要的参数。

这样创建实例很容易,产生的代码读起来也比较容易,因为通过setter的方法名能知道设置的参数是哪一个。

缺点:构造过程被分到了几个调用之中,在构造过程中无法保证JavaBean的一致性。

3.Builder模式

不直接生成想要的对象,而是让客户利用所有必要的参数调用构造器,得到一个builder对象,然后客户端在builder对象上调用类似于setter的方法设置每个可选参数,最后,客户端调用无参的build方法来生成不可变的对象。

public class NutritionFacts {
    private int servingSize;//required
    private int servings;//required
    private int calories;//optional
    private int fat;//optional
    private int sodium;//optional
    private int carbohyrate;//optional

    public static class Builder {//静态Builder类
        private final int servingSize;
        private final int servings;

        private int calories = 0;
        private int fat = 0;
        private int sodium = 0;
        private int carbohyrate = 0;

        public Builder(int servingSize, int servings) {//required参数必须在构造器中提供
            this.servingSize = servingSize;
            this.servings = servings;
        }
            //optional参数在类似setter的方法中赋值
        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public Builder sodium(int val) {
            sodium = val;
            return this;
        }

        public Builder carbohydrate(int val) {
            carbohyrate = val;
            return this;
        }
            //无参的build方法来生成目标实例
        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {//把Builder实例作为构造器参数,buidler会自动填充未赋值的可选域
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohyrate = builder.carbohyrate;
    }

}

实例化NutritionFacts:

NutritionFacts n = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

注意到我们没有给fat域赋值,Builder会自动帮我们填充默认值0

现在构造过程在一条语句上,没有JavaBean模式的缺点,同时具有JavaBean模式的可读性,又能避免重叠构造器模式为不想设置的参数不得不设置的缺点。

Builder模式的缺点:

为了创建对象,必须先创建它的构造器,在十分注重性能的情况下,可能就不太适用了。Builder模式比重叠构造器模式的代码更长,因此只有在很多参数的时候才使用,比如4个或者更多的参数。

时间: 2024-10-13 15:53:47

第二条:遇到多个构造器参数时要考虑用构建器的相关文章

第二条 遇到多个构造器参数时,要考虑用构建器

静态工厂和构造器都有个共同的局限性,就是它们都不能够很好的扩展到大量的可选参数. 如: public class NutritionFacts{ 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 Nu

第二章:创建和销毁对象。ITEM2:遇到多个构造器参数时要考虑用构建器。

如果一个类中有大量的可选参数,有以下几种方式: 1.重叠构造器: package com.twoslow.cha2; /** * 重叠构造器可行,但是当由许多参数的时候,客户端代码很难编写. * @author sai * */ public class Item201 { private final int servingSize; private final int servings; private final int calories; private final int fat; pr

【读书笔记 - Effective Java】02. 遇到多个构造器参数时要考虑用构建器

类有多个可选参数的解决方案:1. 重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且仍然较难以阅读.2. JavaBeans模式,调用一个无参构造器来创造对象,然后调用setter方法来设置每个必要的参数,以及每个相关的可选参数. 缺点:构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态.阻止了把类做成不可变的可能,需要程序员确保线程安全.3. Builder模式,模拟了具名的可选参数. 模式 优 劣 重叠构造器 写法最简单 多参数时候难读.难写.难

遇到多个构造器参数时要考虑用构建器——Effective Java 读书笔记

/** * 如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候. * 与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBeans更加安全. * * @author 刘向峰 * */ public class NutritionFacts { // 所有的参数 private final int servingSize; private final int servin

Effective Item 2 - 遇到多个构造器参数时考虑使用Builder

静态工厂和够构造器有一个共同的局限性:遇到大量的参数时无法很好的扩展. 先说说构造器. 其实field不多时重叠构造器(telescoping constructor)是个不错的方法,易于编写也易于调用,这种方式在参数数量较少时也很常见. 但问题是参数很多(可能越来越多)时,比如(现在已经很难找到对多个参数进行重叠构造的代码了,于是在这里直接引用一下书中的代码): public class NutritionFacts { private final int servingSize; // (m

第二条:遇到多个构造器参数时考虑使用构建器

遇到需要多个参数(参数可分为必需参数和非必需参数)才能实例化一个类的对象时,一般有三种方法: 1.重叠构造器 重叠构造器的方式可行,但是当有许多参数的时候,客户端的代码会很难编写,而且很容器出错. 2.JavaBean式的类 通过setter方法来为实例对象设置Field的值. 3.使用构建器

effective java读书札记值第2条:遇到多个构造器参数时要考虑用构造器

对于一个参数有多个的构造器的类,程序员一向习惯采用重叠的构造器模式. public class Person { private String Id; private String name; private String address; public Person(String id) { Id = id; } public Person(String name, String address) { super(); this.name = name; this.address = addr

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

重叠构造器模式: 创建对象时,我们需要一些必须的参数,从而区分它们,其他可选参数,我们一层一层的赋基本值.这样就提供了用户可选的多种传参方式. 缺点:当有多个参数时,不好处理 JavaBean模式: 通过setter方法,对类进行初始化赋值 Builder模式:(书上最推荐的方式) 书上提供了一个例子,如 NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).......build(); 原文地址:ht

Java 《Effective Java 中文版 第2版》学习笔记 遇到多个构造器时要考虑用构建器

静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数. 当一个类中有若干个必选属性和多个可选属性时,采用重叠构造器模式.JavaBeans模式或者Builder模式,但各有优劣. 当有很多参数的时候,重叠构造器模式下客户端代码会很难编写,并且仍然较难以阅读. JavaBeans模式调用一个无参构造器来创建对象,然后调用setter方法来设置每个必要的参数,以及每个相关的可选参数.因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态.与此相关的另一点不