三、建造者模式

文章目录

  • [1 基本介绍](#1 基本介绍)
  • [2 案例](#2 案例)
    • [2.1 Car 类](#2.1 Car 类)
    • [2.2 CarBuilder 抽象类](#2.2 CarBuilder 抽象类)
    • [2.3 EconomyCarBuilder 类](#2.3 EconomyCarBuilder 类)
    • [2.4 LuxuryCarBuilder 类](#2.4 LuxuryCarBuilder 类)
    • [2.5 CarDirector 类](#2.5 CarDirector 类)
    • [2.6 测试程序](#2.6 测试程序)
    • [2.7 测试结果](#2.7 测试结果)
    • [2.8 总结](#2.8 总结)
  • [3 各角色之间的关系](#3 各角色之间的关系)
    • [3.1 角色](#3.1 角色)
      • [3.1.1 Product ( 产品 )](#3.1.1 Product ( 产品 ))
      • [3.1.2 Builder ( 抽象建造者 )](#3.1.2 Builder ( 抽象建造者 ))
      • [3.1.3 ConcreteBuilder ( 具体建造者 )](#3.1.3 ConcreteBuilder ( 具体建造者 ))
      • [3.1.4 Director ( 指挥者 )](#3.1.4 Director ( 指挥者 ))
    • [3.2 类图](#3.2 类图)
  • [4 注意事项](#4 注意事项)
  • [5 在源码中的使用](#5 在源码中的使用)
    • [5.1 RequestConfig.Builder 的源码](#5.1 RequestConfig.Builder 的源码)
    • [5.2 使用 RequestConfig.Builder 构建对象](#5.2 使用 RequestConfig.Builder 构建对象)
    • [5.3 总结](#5.3 总结)
  • [6 优点](#6 优点)
  • [7 使用场景](#7 使用场景)
  • [8 总结](#8 总结)

1 基本介绍

建造者模式 (Builder Pattern)是一种 创建型 设计模式,该模式指出:将一个复杂对象的 构造 与它的 表现 (对象的 类型属性 ) 分离,使同样的构建过程可以创建不同表现的对象。它允许用户只通过指定复杂对象的 类型内容 来构建它们,而不需要知道内部的具体构建细节。

2 案例

本案例演示了两种类型(经济型和豪华型)的汽车生产(只涉及了组装发动机、轮胎、方向盘):

2.1 Car 类

java 复制代码
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;
    }

    @Override
    public String toString() {
        return "Car{" +
                "engine='" + engine + '\'' +
                ", wheel='" + wheel + '\'' +
                ", steeringWheel='" + steeringWheel + '\'' +
                '}';
    }
}

2.2 CarBuilder 抽象类

java 复制代码
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 类

java 复制代码
public class EconomyCarBuilder extends CarBuilder { // 经济型汽车建造者
    private Car car;

    public EconomyCarBuilder() {
        this.car = new Car();
    }

    @Override
    public CarBuilder assembleEngine() {
        car.setEngine("小排量发动机");
        return this;
    }

    @Override
    public CarBuilder assembleWheel(String wheel) {
        car.setWheel(wheel);
        return this;
    }

    @Override
    public CarBuilder assembleSteeringWheel() {
        car.setSteeringWheel("常规方向盘");
        return this;
    }

    @Override
    public Car build() {
        return car;
    }
}

2.4 LuxuryCarBuilder 类

java 复制代码
public class LuxuryCarBuilder extends CarBuilder { // 豪华型汽车建造者
    private Car car;

    public LuxuryCarBuilder() {
        this.car = new Car();
    }

    @Override
    public CarBuilder assembleEngine() {
        car.setEngine("大排量发动机");
        return this;
    }

    @Override
    public CarBuilder assembleWheel(String wheel) {
        car.setWheel(wheel);
        return this;
    }

    @Override
    public CarBuilder assembleSteeringWheel() {
        car.setSteeringWheel("带加热功能的方向盘");
        return this;
    }

    @Override
    public Car build() {
        return car;
    }
}

2.5 CarDirector 类

java 复制代码
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 测试程序

java 复制代码
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 注意事项

  1. 抽象建造者 的设计应包含产品 所有 部件的创建和装配方法,确保每个具体建造者都实现这些方法(使用 abstract 关键字修饰)。
  2. 具体建造者 的编写应根据产品的 组成部分组装顺序 来实现抽象建造者接口。
  3. 指挥者 需要根据 一定的逻辑和顺序 来调用具体建造者的方法,以组织产品的创建过程。

5 在源码中的使用

5.1 RequestConfig.Builder 的源码

java 复制代码
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 的依赖:

xml 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

以下是使用 RequestConfig.Builder 生成 RequestConfig 对象的一个示例:

java 复制代码
RequestConfig.Builder builder = RequestConfig.custom()
        .setSocketTimeout(3000)
        .setConnectTimeout(3000)
        .setConnectionRequestTimeout(3000);
RequestConfig config = builder.build();

5.3 总结

Apache HttpClient 中的 RequestConfig.Builder 是一个典型的建造者类示例,它用于构建 RequestConfig 对象,该对象包含了请求的配置信息。

6 优点

  • 分离构建和表现:建造者模式将一个复杂对象的构建过程与其表现分离,从而可以更灵活地构建不同表现的对象。
  • 易于扩展 :由于 具体建造者 和 指导者 之间的 松耦合 关系,可以在不影响客户端代码(即不需要修改 使用 Director 建造对象的代码)的前提下,新增 或 替换 具体建造者,从而 扩展 或 修改 构建过程。
  • 更好的封装性 :由于建造者模式将复杂对象的构建过程 封装 在具体建造者中,客户端只需要调用 Directorconstruct() 方法即可,无需关心具体的构建过程。
  • 对象构建的精确控制 :通过建造者模式,可以在 Director精确地 控制对象的构建过程,包括每个部分的 构建顺序 、构建时的 参数设置 等,从而得到更精确的结果。

7 使用场景

  • 创建的对象较 复杂 ,由多个部件构成,各部件面临着复杂的变化,但构件间的 建造顺序是稳定的
  • 创建复杂对象的算法 独立于 该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表现是独立的。

8 总结

建造者模式通过分离复杂对象的构建和表示,提供了更灵活、更可扩展的构建过程,是处理 复杂对象构建问题 的有效手段。

相关推荐
测开小菜鸟1 小时前
使用python向钉钉群聊发送消息
java·python·钉钉
P.H. Infinity2 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天2 小时前
java的threadlocal为何内存泄漏
java
caridle2 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
^velpro^2 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋33 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx
秋の花3 小时前
【JAVA基础】Java集合基础
java·开发语言·windows
小松学前端3 小时前
第六章 7.0 LinkList
java·开发语言·网络
Wx-bishekaifayuan3 小时前
django电商易购系统-计算机设计毕业源码61059
java·spring boot·spring·spring cloud·django·sqlite·guava
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源