概念定义

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. 解决Android Screen Monitor在android8.0及以上系统报错:"E/Screenshot: Unsupported protocol: 2"

    1.打开命令窗口,切换到 asm.jar 所在目录,执行 java -jar asm.jar,正常情况下打开后连接上设备会显示出画面 2.但是在android8.0以上系统该asm.jar包就无法正常 ...

  2. 基于django的个人博客网站建立(六)

    基于django的个人博客网站建立(六) 前言 今天主要完成的是项目在腾讯云服务器上ubuntu16.04+django+mysql+uwsig+nginx的部署过程网站效果可点击这里访问 主要内容 ...

  3. csp2019后的感慨

    你还记得曾经加入oi的初衷吗? ... 我们都不想输,可谁都没有赢... --前言 没有太大的感想,也不配去写感想...就记录一下初学者失败的原因吧.希望看过的人能引以为戒. 做题的时候,不到万不得已 ...

  4. python 导入同级目录文件时报错

    当你import的时候,python解释器只会在sys.path这个变量(一个list,你可以print出来看)里面的路径中找可能匹配的package或module. 而一个package跟一个普通文 ...

  5. Jenkins学习安装配置和使用

    为了能够频繁地将软件的最新版本,及时.持续地交付给测试团队及质量控制团队,以供评审,所以引入持续集成工具Jenkins,从而实现公司新产品持续集成,自动化部署. 环境准备 ●操作系统:Windows1 ...

  6. Zuul 修改 请求头、响应头 (死磕)

    疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列 [博客园总入口 ] 架构师成长+面试必备之 高并发基础书籍 [Netty Zookeeper Redis 高并发实战 ] 前言 Crazy ...

  7. (转)Python- sklearn之最小二乘法

    最小二乘法:https://baike.baidu.com/item/%E6%9C%80%E5%B0%8F%E4%BA%8C%E4%B9%98%E6%B3%95/2522346?fr=aladdin ...

  8. (转)RocketMQ工作原理

    原文:https://blog.csdn.net/lyly4413/article/details/80838716 1.消息中间件的发展: 第一代以ActiveMQ为代表,遵循JMS(java消息服 ...

  9. C# 利用itextsharp、Spire配合使用为pdf文档每页添加水印

    下载类库: 直接下载 引入类库 功能实现 using iTextSharp.text.pdf; using Spire.Pdf; using Spire.Pdf.Graphics; using Sys ...

  10. 中文版 Apple 官方 Swift 教程《The Swift Programming Language》

    简介 欢迎使用 Swift 关于 Swift 版本兼容性 Swift 初见 Swift 版本历史记录 Swift 教程 基础部分 基本运算符 字符串和字符 集合类型 控制流 函数 闭包 枚举 类和结构 ...