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

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

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

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

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

  下面就是它的示例:

 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 static class Builder {
// Required parameters
private final int servingSize;
private final int servings; // Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0; public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
} public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
} public NutritionFacts build() {
return new NutritionFacts(this);
}
} private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
} public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
}
}

  它在检验约束时将参数从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

Java 构造器 遇到多个构造器时要考虑用构建器的更多相关文章

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

    类有多个可选参数的解决方案: 1. 重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且仍然较难以阅读. 2. JavaBeans模式,调用一个无参构造器来创造对象,然后调用sett ...

  2. 链式编程:遇到多个构造器参数(Constructor Parameters)时要考虑用构建器(Builder)

    public class NutritionFacts { private final int servingSize; private final int servings; private fin ...

  3. 遇到多个构造器参数时要考虑用构建器 builder 模式 JavaBean 线程安全

    effective java p9 JavaBeans模式阻止了把类做成不可变的可能,这需要程序员付出额外的努力来确保它的线程安全.

  4. 解析《Effective Java》之多个构造器、Javabeans模式和Builder模式

    最近看<Effective Java>这本被很多同行称为神作的书,但是这本书很多地方缺少了举例不好懂,下面是关于我对书上知识的理解. 一.<Effective Java>中文版 ...

  5. Effective Java 之-----静态工厂与构造器

    一. 考虑用静态工厂方法代替构造器: 1)静态工厂方法与构造器不同的第一大优势在于:他们有名称.当一个类需要多个带有相同签名的构造器时,就用静态方法代替构造器,并慎重的选择名称以突出他们间的区别: 2 ...

  6. 构造器参数过多时考虑使用构建器(Builder)

    一.静态工厂和构造器的局限性 面对需要大量可选参数才能构建对象时,静态工厂和构造器并不能随着可选参数的增加而合理扩展. 假设创建一个类Person需要使用大量的可选参数,其中两个参数是必填的,剩下的都 ...

  7. effective java之使用构建器来创建对象

    第二章第2条:遇到多个构造器参数时要考虑使用构建器(builder) 就是建造者模式(不直接生成想要的对象,而是让客户端利用所有有必要的参数调用构造器或者静态工厂)直接上代码 package com. ...

  8. Java继承之再谈构造器

    目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...

  9. Java构造器与构建器的使用

    我们在平常类的构建过程中,可能会面临很多问题,可扩张性.安全性等等.想象一下,这样一个场景,我们现在要创建一个类,其中有6个属性,其中又有4个属性的值是不太确定的(可能某个对象就不需要其中的某个值), ...

随机推荐

  1. Senparc.Weixin微信开发(1) 开发验证

    官方系列教程 http://www.cnblogs.com/szw/archive/2013/05/20/3089479.html 登录微信公众平台后-左侧找到开发--启用服务器配置 这样,我们才可以 ...

  2. CAS单点登录--转载

    一:单点登录介绍 单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要 登录一次 就可以访问所有相 ...

  3. 谷歌浏览器Software Reporter Tool长时间占用CPU解决办法

    什么是Software Reporter Tool Software Reporter Tool是一个Chrome清理工具,用于清理谷歌浏览器中不必要或恶意的扩展,应用程序,劫持开始页面等等.当你安装 ...

  4. GoLang函数参数的传递练习

    春节买的GO方面的书,看了一次.现在撸一些代码,作为练习. // Copyright © 2019 NAME HERE <EMAIL ADDRESS> // // Licensed und ...

  5. Aho-Corasick算法实现(简单关键字过滤)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  6. bzoj4773: 负环

    题解: 网上还有一种spfa+深度限制的算法 https://www.cnblogs.com/BearChild/p/6624302.html 是不加队列优化的spfa,我觉得复杂度上限是bellma ...

  7. 在ionic2中集成swiper插件

    1. 下载官方的js和css文件分别放在assets下的js和css文件夹,然后在index.html中引入 <!DOCTYPE html> <html lang="en& ...

  8. mysql主从复制(半同步方式)

    mysql主从复制(半同步方式) 博客分类: MySQL mysqlreplication复制  一.半同步复制原理介绍 1. 优点 当事务返回客户端成功后,则日志一定在至少两台主机上存在. MySQ ...

  9. python--类中的对象方法、类方法、静态方法的区别

    1.对象方法:顾名思义,是对类实例化后的对象有效的,由对象调用 2.类方法:第一个参数是cls(当前类),是对当前类做的额外的处理,类方法需要用类去调用,而不是实例对象调用 3.静态方法:没有参数!没 ...

  10. Codeforces 986D Perfect Encoding FFT 分治 高精度

    原文链接https://www.cnblogs.com/zhouzhendong/p/9161557.html 题目传送门 - Codeforces 986D 题意 给定一个数 $n(n\leq 10 ...