文章目录
- 1 基本介绍
- 2 案例
- 2.1 Car 类
- 2.2 CarBuilder 抽象类
- 2.3 EconomyCarBuilder 类
- 2.4 LuxuryCarBuilder 类
- 2.5 CarDirector 类
- 2.6 测试程序
- 2.7 测试结果
- 2.8 总结
- 3 各角色之间的关系
- 3.1 角色
- 3.1.1 Product ( 产品 )
- 3.1.2 Builder ( 抽象建造者 )
- 3.1.3 ConcreteBuilder ( 具体建造者 )
- 3.1.4 Director ( 指挥者 )
- 3.2 类图
- 4 注意事项
- 5 在源码中的使用
- 5.1 RequestConfig.Builder 的源码
- 5.2 使用 RequestConfig.Builder 构建对象
- 5.3 总结
- 6 优点
- 7 使用场景
- 8 总结
1 基本介绍
建造者模式(Builder Pattern)是一种 创建型 设计模式,该模式指出:将一个复杂对象的 构造 与它的 表现 (对象的 类型 及 属性) 分离,使同样的构建过程可以创建不同表现的对象。它允许用户只通过指定复杂对象的 类型 和 内容 来构建它们,而不需要知道内部的具体构建细节。
2 案例
本案例演示了两种类型(经济型和豪华型)的汽车生产(只涉及了组装发动机、轮胎、方向盘):
2.1 Car 类
public class Car { // 汽车类,假设内部很复杂private String engine; // 发动机private String wheel; // 轮胎private String steeringWheel; // 方向盘public String getEngine() {return engine;}public void setEngine(String engine) {this.engine = engine;}public String getWheel() {return wheel;}public void setWheel(String wheel) {this.wheel = wheel;}public String getSteeringWheel() {return steeringWheel;}public void setSteeringWheel(String steeringWheel) {this.steeringWheel = steeringWheel;}@Overridepublic String toString() {return "Car{" +"engine='" + engine + '\'' +", wheel='" + wheel + '\'' +", steeringWheel='" + steeringWheel + '\'' +'}';}
}
2.2 CarBuilder 抽象类
public abstract class CarBuilder { // 抽象的汽车建造者,也可以定义成接口 interface// 以下三个方法的返回值都是 CarBuilder,从而可以使用 链式编程public abstract CarBuilder assembleEngine(); // 组装发动机public abstract CarBuilder assembleWheel(String wheel); // 组装车轮public abstract CarBuilder assembleSteeringWheel(); // 组装方向盘public abstract Car build(); // 返回构建的对象
}
2.3 EconomyCarBuilder 类
public class EconomyCarBuilder extends CarBuilder { // 经济型汽车建造者private Car car;public EconomyCarBuilder() {this.car = new Car();}@Overridepublic CarBuilder assembleEngine() {car.setEngine("小排量发动机");return this;}@Overridepublic CarBuilder assembleWheel(String wheel) {car.setWheel(wheel);return this;}@Overridepublic CarBuilder assembleSteeringWheel() {car.setSteeringWheel("常规方向盘");return this;}@Overridepublic Car build() {return car;}
}
2.4 LuxuryCarBuilder 类
public class LuxuryCarBuilder extends CarBuilder { // 豪华型汽车建造者private Car car;public LuxuryCarBuilder() {this.car = new Car();}@Overridepublic CarBuilder assembleEngine() {car.setEngine("大排量发动机");return this;}@Overridepublic CarBuilder assembleWheel(String wheel) {car.setWheel(wheel);return this;}@Overridepublic CarBuilder assembleSteeringWheel() {car.setSteeringWheel("带加热功能的方向盘");return this;}@Overridepublic Car build() {return car;}
}
2.5 CarDirector 类
public class CarDirector { // 建造汽车的指挥者private CarBuilder carBuilder;public CarDirector(CarBuilder carBuilder) {this.carBuilder = carBuilder;}public Car construct(String wheel) { // 构建一个汽车对象return carBuilder.assembleEngine().assembleWheel(wheel).assembleSteeringWheel().build(); // 使用了 链式编程}
}
2.6 测试程序
public class Main { // 测试程序public static void main(String[] args) {CarDirector carDirector = new CarDirector(new EconomyCarBuilder());Car economyCar = carDirector.construct("耐用的轮胎");System.out.println(economyCar);carDirector = new CarDirector(new LuxuryCarBuilder());Car luxuryCar = carDirector.construct("噪音小的轮胎");System.out.println(luxuryCar);}
}
2.7 测试结果
Car{engine='小排量发动机', wheel='耐用的轮胎', steeringWheel='常规方向盘'}
Car{engine='大排量发动机', wheel='噪音小的轮胎', steeringWheel='带加热功能的方向盘'}
2.8 总结
可以发现,在 CarDirector
构建对象时,既不需要了解是哪个 CarBuilder
的子类在参与构建,也不需要了解 其方法的具体实现,只是简单地传递参数、调用方法即可构建 Car
这个“复杂”(假设它很复杂)的对象。
此外,如果想要构建一种新的(属性不同) Car
,只需要继承 CarBuilder
抽象类,并实现其中的方法,就可以将其作为构造 CarDirector
的参数,从而使用 CarDirector
建造 Car
了。
3 各角色之间的关系
3.1 角色
3.1.1 Product ( 产品 )
该角色是一个 复杂 的对象,由 多个部件 组成,具有 一定的功能和特点,不能 直接 通过构造器得到。本案例中,Car
类扮演这个角色。
3.1.2 Builder ( 抽象建造者 )
该角色负责 定义 创建产品对象的各个部件的 方法,并且 定义 返回构建的产品对象的 方法。本案例中,CarBuilder
抽象类扮演这个角色。
3.1.3 ConcreteBuilder ( 具体建造者 )
该角色负责 实现 创建产品对象的各个部件的 方法,并且 实现 返回构建的产品对象的 方法。本案例中,EconomyCarBuilder, LuxuryCarBuilder
类扮演这个角色。
3.1.4 Director ( 指挥者 )
该角色负责 按照一定的顺序 使用 创建产品对象的各个部件的 方法。它并不依赖具体的建造者,只调用在抽象建造者中定义的方法。本案例中,CarDirector
类扮演这个角色。
3.2 类图
说明:这是 传统的 建造者模式的类图,如果希望支持 链式编程,则可以把建造者的所有 buildPart()
方法的返回值从 void
改为 Builder
。另外,这些 buildPart()
方法不一定没有参数,根据实际情况而定。
4 注意事项
- 抽象建造者 的设计应包含产品 所有 部件的创建和装配方法,确保每个具体建造者都实现这些方法(使用
abstract
关键字修饰)。 - 具体建造者 的编写应根据产品的 组成部分 和 组装顺序 来实现抽象建造者接口。
- 指挥者 需要根据 一定的逻辑和顺序 来调用具体建造者的方法,以组织产品的创建过程。
5 在源码中的使用
5.1 RequestConfig.Builder 的源码
public static class Builder { // Builder 是 RequestConfig 的静态内部类private boolean expectContinueEnabled;private HttpHost proxy;private InetAddress localAddress;// ... 省略很多成员变量Builder() {super();// ... 省略很多赋值}public Builder setExpectContinueEnabled(final boolean expectContinueEnabled) {this.expectContinueEnabled = expectContinueEnabled;return this;}public Builder setProxy(final HttpHost proxy) {this.proxy = proxy;return this;}public Builder setLocalAddress(final InetAddress localAddress) {this.localAddress = localAddress;return this;}// ... 省略了很多方法public RequestConfig build() {return new RequestConfig(expectContinueEnabled,proxy,localAddress,// ... 省略了很多参数normalizeUri);}
}
5.2 使用 RequestConfig.Builder 构建对象
先确保你的项目中已经包含了 Apache HttpClient 的依赖,这里给出 Maven 的依赖:
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
以下是使用 RequestConfig.Builder
生成 RequestConfig
对象的一个示例:
RequestConfig.Builder builder = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).setConnectionRequestTimeout(3000);
RequestConfig config = builder.build();
5.3 总结
Apache HttpClient 中的 RequestConfig.Builder
是一个典型的建造者类示例,它用于构建 RequestConfig
对象,该对象包含了请求的配置信息。
6 优点
- 分离构建和表现:建造者模式将一个复杂对象的构建过程与其表现分离,从而可以更灵活地构建不同表现的对象。
- 易于扩展:由于 具体建造者 和 指导者 之间的 松耦合 关系,可以在不影响客户端代码(即不需要修改 使用
Director
建造对象的代码)的前提下,新增 或 替换 具体建造者,从而 扩展 或 修改 构建过程。 - 更好的封装性:由于建造者模式将复杂对象的构建过程 封装 在具体建造者中,客户端只需要调用
Director
的construct()
方法即可,无需关心具体的构建过程。 - 对象构建的精确控制:通过建造者模式,可以在
Director
中 精确地 控制对象的构建过程,包括每个部分的 构建顺序、构建时的 参数设置 等,从而得到更精确的结果。
7 使用场景
- 创建的对象较 复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的 建造顺序是稳定的。
- 创建复杂对象的算法 独立于 该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表现是独立的。
8 总结
建造者模式通过分离复杂对象的构建和表示,提供了更灵活、更可扩展的构建过程,是处理 复杂对象构建问题 的有效手段。