概念定义

Builder模式是一步一步创建一个复杂对象的创建型模式。该模式将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示隔离开来。

应用场景

  • 对象创建过程比较复杂,或对创建顺序或组合有依赖(经典Builder模式,可参阅GOF《设计模式》)。
  • 创建对象时所需参数较多,且包含较多可选参数(变种Builder模式,可参阅《Effective Java》构建器小节)。

示例代码

本节侧重变种Builder模式,示例代码如下:

public class RobustPerson {
// 必要参数
private final int id; // 所有属性都被final修饰
private final String name; // 可选参数
private final int age;
private final String gender;
private final double height;
private final int weight; private RobustPerson(Builder builder) { // 构造方法私有,即客户端不能直接创建RobustPerson对象
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
this.gender = builder.gender;
this.height = builder.height;
this.weight = builder.weight;
} public static final class Builder {
// 必要参数
private final int id; // 必要属性被final修饰
private final String name; // 可选参数
private int age;
private String gender;
private double height;
private int weight; public Builder(int id, String name) { this.id = id; this.name = name; } // 必要参数通过构造方法赋值 public Builder age(int age) { this.age = age; return this; } // 可选参数通过同名方法赋值
public Builder gender(String gender) { this.gender = gender; return this; }
public Builder height(double height) { this.height = height; return this; }
public Builder weight(int weight) { this.weight = weight; return this; } public RobustPerson build() {
RobustPerson person = new RobustPerson(this);
// 复杂业务语义校验,对于校验不通过场景,抛出异常
if (person.height != 0 && person.weight != 0) { // Builder对象并非线程安全的,不能用this.xxx校验
double bmi = person.weight / (person.height * person.height);
if (bmi < 18 || bmi > 25) { // 身体质量指数(BMI)低于18或高于25时表示不健康
throw new IllegalArgumentException(person.name+" NOT A ROBUST PERSON!");
}
}
return person;
}
} public Builder toBuilder() { // 克隆
return new Builder(this.id, this.name).age(this.age)
.gender(this.gender).height(this.height).weight(this.weight);
} @Override
public String toString() {
return name + "{" + "id=" + id + ", age=" + age + ", gender='" + gender + '\'' +
", height=" + height + "m, weight=" + weight + "kg}";
}
}

测试类如下:

public class BuilderTest {
public static void main(String[] args) {
RobustPerson jack = new RobustPerson.Builder(1, "Jack")
.age(18).gender("male").height(1.70).weight(65).build();
System.out.println(jack); System.out.println("Jack keeps eating too much...");
System.out.println(jack.toBuilder().weight(80).build());
}
}

运行后输出:

Jack{id=1, age=18, gender='male', height=1.7m, weight=65kg}
Jack keeps eating too much...
Exception in thread "main" java.lang.IllegalArgumentException: Jack NOT A ROBUST PERSON!
at builder.RobustPerson$Builder.build(RobustPerson.java:48)
at builder.BuilderTest.main(BuilderTest.java:14)

关键特点

结合上节示例代码,可知Builder模式创建对象具有以下特点:

  • RobustPerson类的构造方法是私有的,即客户端不能直接创建RobustPerson对象。
  • RobustPerson类不可变(线程安全的): 所有属性都被final修饰,在构造方法中设置参数值,并且不对外提供Setter方法(Getter方法可选)。
  • 静态内部类Builder与RobustPerson拥有相同的成员变量,且Builder内通过构造方法处理final修饰的必要参数,通过同名方法处理可选参数。
  • Builder内的build()方法调用RobustPerson的私有构造函数来创建RobustPerson对象,且客户端只能通过该build()方法创建对象(从而避免Invalid状态)。
  • Builder对象并不具有线程安全性。如果需要对RobustPerson对象的参数强加约束条件,应对build()方法所创建的RobustPerson对象进行检验。
  • 当创建多个对象且对象大多数属性值都相同时,通过toBuilder()可简单高效地克隆对象,仅针对不同的属性重新设置值。
  • Builder模式使用链式调用,可读性更佳。

但Builder模式也不可避免地存在自身的缺点。例如:

  • 创建对象前必须先创建它的构建器,消耗内存(若仅需要链式调用可仿照Builder类定义目标类)。
  • Builder模式存在冗长的样板代码(可借助InnerBuilder或Lombok插件自动生成)。

业界实践

  • StringBuilder(JDK)
  • JobBuilder(quartz-2.3.0.jar)
  • SessionFactoryBuilder等(hibernate-core-5.3.6.Final.jar)

Java设计模式:Builder(构建器)模式的更多相关文章

  1. 深入探索Java设计模式之构建器模式(五)

    抽丝剥茧 细说架构那些事——[优锐课] 简单的程序不需要大量的设计过程,因为它们只关注有限的解决方案,仅使用几个类.大型程序专注于广泛的设计,该设计比好的设计范例的任何其他属性都更能利用可重用性.宏伟 ...

  2. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  3. Java设计模式-Builder构造者模式

    介绍: 构造者模式,又称之为建造者模式,建造者模式,单例模式以及工厂模式都属于创建型模式1应用场景 今天学mybatis的时候,知道了SQLSessionFactory使用的是builder模式来生成 ...

  4. java设计模式之七装饰器模式(Decorator)

    顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,关系图如下: Source类是被装饰类,Decorator类是一个 ...

  5. java设计模式之 装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...

  6. Java设计模式之装饰器模式

    1.装饰器模式的定义(保持接口,扩展功能) Decorate装饰器,顾名思义,就是动态的给一个对象添加一些额外的职责,就好比对房子进行装修一样. 2.装饰器模式的特征 具有一个装饰对象. 必须拥有与被 ...

  7. java设计模式之装饰器模式以及在java中作用

    在JAVA I/O类库里有很多不同的功能组合情况,这些不同的功能组合都是使用装饰器模式实现的,下面以FilterInputStream为例介绍装饰器模式的使用  FilterInputStream和F ...

  8. java 设计模式 之 装饰器模式

    装饰器模式的作用 在不修改原先对象核心的功能的情况下,对功能进行增强. 增强对象的功能的途径 通过类继承的方式,对父对象进行增强操作,例如造车是父类,改装跑车,跑车加大灯,改装房车,房车加私人电影院. ...

  9. java设计模式4--建造者模式(Builder)

    本文地址:http://www.cnblogs.com/archimedes/p/java-builder-pattern.html,转载请注明源地址. 建造者模式 将一个复杂对象的构建与它的表示分离 ...

随机推荐

  1. 如何写一个Python万能装饰器,既可以装饰有参数的方法,也可以装饰无参数方法,或者有无返回值都可以装饰

    Python中的装饰器,可以有参数,可以有返回值,那么如何能让这个装饰器既可以装饰没有参数没有返回值的方法,又可以装饰有返回值或者有参数的方法呢?有一种万能装饰器,代码如下: def decorate ...

  2. 【tf.keras】tensorflow datasets,tfds

    一些最常用的数据集如 MNIST.Fashion MNIST.cifar10/100 在 tf.keras.datasets 中就能找到,但对于其它也常用的数据集如 SVHN.Caltech101,t ...

  3. 14. java面向对象 - 基础

    一.面向对象主线 1. Java类及类的成员:属性.方法.构造器.代码块.内部类 2. 面向对象三大特征:封装.继承.多态.(抽象性) 3. 其他关键字:this.super.static.final ...

  4. numpy-np.ceil,np.floor,np.expand_dims方法

    np.ceil(多维数组):对多维数组的各个数向上取整 np.floor(多维数组):对多维数组的各个数向下取整 np.expand_dims(x,axis = 0):在x的第一维度上插入一个维度,a ...

  5. 急速下载pandas

    使用国内源进行下载: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua ...

  6. 即将是史上最全的meta大全

    本文的目的是搜集当前主流的meta配置,方便开发者快速开发调试.在这里不会做各种meta的深入分析,只是简单的介绍,让大家知道有这个东西. meta简述 meta用于描述 HTML 文档的元数据.通常 ...

  7. python文件夹遍历,文件操作,获取文件修改创建时间

    在Python中,文件操作主要来自os模块,主要方法如下: os.listdir(dirname):列出dirname下的目录和文件os.getcwd():获得当前工作目录os.curdir:返回当前 ...

  8. 工作总结汇报公司介绍产品宣传品牌展示企业文化PPT模

    清晰明了:在工作总结会议上都是要严肃为主,搞的花里胡哨既不好看也让领导有不好的影响:微粒体:模板样式立体效果非常好,能够一把将观众眼球给吸引住:样式齐全:各种PPT样式都有,能够承载工作汇报各种内容: ...

  9. spark SQL、RDD、Dataframe总结

  10. PHP strstr 字符串函数

    定义和用法 strstr - 查找字符串的首次出现 版本支持 PHP4 PHP5 PHP7 支持 支持 支持 V5.3.0 新增可选的 before_needle 参数. V4.3.0 strstr( ...