设计模式——建造者模式

文章目录

    • 一、建造者模式
      • [1.1 建造者模式的定义](#1.1 建造者模式的定义)
      • [1.2 建造者模式的参与者](#1.2 建造者模式的参与者)
      • [1.3 建造者模式的优点](#1.3 建造者模式的优点)
      • [1.4 建造者模式的使用场景](#1.4 建造者模式的使用场景)
    • 二、普通案例
      • [2.1 代码设计](#2.1 代码设计)
      • [2.2 实现代码](#2.2 实现代码)
    • [三、Lombok 实现案例](#三、Lombok 实现案例)
      • [3.1 @Builder 使用方法](#3.1 @Builder 使用方法)
      • [3.2 @Builder 实际所作工作](#3.2 @Builder 实际所作工作)
    • 参考资料

一、建造者模式

1.1 建造者模式的定义

建造者模式(Builder Pattern)也叫做生成器模式,其定义如下:

Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)

构建和表示的含义如下:

构建: 创建对象的过程,涉及按照一定的步骤、顺序来组合对象的各个部分,最终生成一个完整的对象。例如,构造一辆汽车包括安装发动机、安装轮胎、装配车身等步骤。论汽车的类型如何,这些基本步骤都是相同的。

表示:构建对象的具体形态或形式。不同的表示意味着通过同样的构建步骤,可以生成不同的对象形式。例如,汽车可以有不同的表示,比如一辆跑车和一辆卡车。尽管构建的过程都包括安装发动机、轮胎和车身等步骤,但不同的表示会在每个步骤中有所不同,比如跑车使用的是高性能发动机,而卡车可能使用的是大功率发动机。

同样的构建步骤所生成的对象的具体形式,可能会因构造器的不同而有所变化。

1.2 建造者模式的参与者

在建造者模式中,不同参与者的作用如下:

  • Product(产品): 复杂对象的类,表示需要创建的复杂对象, 通常包含多个部件(字段)。它是建造者模式的最终生成目标。
  • Builder(抽象建造者) :定义了构建 Product 各部分的抽象接口。该接口规定了用于创建产品各个部件的方法,但并不实现这些方法。还包含一个返回最终产品对象的方法。
  • ConcreteBuilder(具体建造者) :具体化了创建产品各个部件的方法,负责跟踪构建过程的状态,并最终生成产品。每个具体建造者可以创建产品的不同表示
  • Director(指挥者) :指挥者类负责控制构建过程的顺序,指导 Builder 来创建产品。换句话说,它定义了构建产品的步骤顺序,确保每个步骤按特定的顺序执行。

注意,Director 和 Builder 是聚合关系, 共同协作来完成对象的创建。

1.3 建造者模式的优点

  • 封装性。不关注每一个具体的模型内部如何实现。
  • 便于控制细节风险。由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

1.4 建造者模式的使用场景

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
  • 如果类的属性之间有一定的依赖关系或者约束条件(源自设计模式之美),那么就可以考虑使用 Builder 设计模式。
  • 产品类非常复杂,这个时候使用建造者模式非常合适。

二、普通案例

2.1 代码设计

具体工作流程为:

  • 构建 :我们定义一个构造器(Builder)类,用来逐步创建复杂对象。这个类包含生成对象的多个步骤(如"安装发动机"、"安装轮胎")。

  • 表示 :我们定义不同的具体构造器(ConcreteBuilder)类,每个构造器生成一个特定的表示(如"跑车"或"卡车")。

2.2 实现代码

本案例的实现代码位于 java-demos/builder-pattern at main · idealzouhu/java-demos (github.com)

三、Lombok 实现案例

Lombok 库中的注解 @Builder 可以自动创建一个实现建造者模式的类。当在类上添加@Builder注解后,Lombok会自动生成一个建造者类,可以在类的外部使用建造者模式来创建该类的实例。

实际上,仅使用建造者模式创建复杂对象时,我们有时候可能并不需要创建 Director 类, 而是在创建对象的时候手动指定产品创建步骤

3.1 @Builder 使用方法

创建一个类,使用相应注解

java 复制代码
@Data
@Builder
public class User {
    // 用户 ID
    private String userId;

    // 用户名
    private String username;

}

public class BuilderPatternExample {
    public static void main(String[] args) {
        User user = User.builder()
                .userId("123456")
                .username("zhangsan")
                .build();
        System.out.println(user); // 返回结果为 User(userId=123456, username=zhangsan)
    }
}

3.2 @Builder 实际所作工作

查看编译后的 User 类的源码, 可以发现在内部创建了具体建造者 UserBuilder

java 复制代码
public class User {
    private String userId;
    private String username;

    @Generated
    public static UserBuilder builder() {
        return new UserBuilder();
    }
    
    // setter,getter,equal,construct,hashCode, toString等方法
    ...
    
     @Generated
    public static class UserBuilder {
        @Generated
        private String userId;
        @Generated
        private String username;

        @Generated
        UserBuilder() {
        }

        @Generated
        public UserBuilder userId(final String userId) {
            this.userId = userId;
            return this;
        }

        @Generated
        public UserBuilder username(final String username) {
            this.username = username;
            return this;
        }

        @Generated
        public User build() {
            return new User(this.userId, this.username);
        } 
    }
}

参考资料

《设计模式之禅 (第2版)》

秒懂设计模式之建造者模式(Builder pattern) - 知乎 (zhihu.com)

Hutool如何使用Builder模式创建线程池 (yuque.com)

相关推荐
多加点辣也没关系10 小时前
设计模式-工厂方法模式
设计模式·工厂方法模式
likerhood10 小时前
ConcurrentHashMap详细讲解(java)
java·开发语言·性能优化
源码集结号11 小时前
基于 Spring Boot + JPA + MySQL的上门家政系统代码示例
java·前端·后端
程序员老邢12 小时前
【技术底稿 32】Nginx 经典大坑复盘:本机公网域名自环代理,导致接口返回首页 / 404 实战排障
java·运维·nginx·前后端分离·技术底稿·后端部署
该昵称用户已存在13 小时前
从成本中心到价值引擎:MyEMS 开源系统激活企业能源数据资产
java·后端·struts
隐退山林13 小时前
JavaEE进阶:SpringBoot配置文件
java·spring boot·java-ee
阿维的博客日记13 小时前
求解深分页问题,last pk适合什么情况
java·mysql·深分页
极客先躯14 小时前
高级java每日一道面试题-2025年12月09日-实战篇[Docker]-如何配置 Docker 的日志驱动?有哪些日志驱动可选?
java·docker·日志驱动的作用与配置层级·日志驱动全览与对比·日志驱动配置的要点·日志标签定制·容器与宿主机时间戳
rabbit_pro14 小时前
Spring AI使用Ollama
java·人工智能·spring