当前位置: 首页 > news >正文

Java实现建造者模式和源码中的应用

Java实现建造者模式(Builder Pattern)

文章目录

  • Java实现建造者模式(Builder Pattern)
    • 案例:汉堡制作
    • 建造者模式的核心角色
    • 代码实现:汉堡制作 🍔
      • 内部类实现:
        • Step 1:产品类 Burger
        • Step 2:指挥者 Director
        • Step 3:客户端代码
        • 结果
        • 总结
      • 抽象类实现
        • Step 1:产品类 Burger
        • Step 2:抽象的 Builder 类
        • Step 3:具体的 Builder 类
        • Step 4:指挥者 Director
        • Step 5:客户端代码
        • 输出结果
        • 总结:使用抽象类的优点
    • 源码中的应用
      • 1. `StringBuilder` 和 `StringBuffer`
      • `2.java.util.stream.Stream.Builder`
      • 3.Lombok 中的 `@Builder` 注解
        • 示例:使用 `@Builder` 注解
    • 总结

建造者模式(Builder Pattern)是一种创建型设计模式,主要用于分步骤构建复杂对象。与工厂模式不同的是,建造者模式允许你逐步地构造对象,并且不同的步骤可以有不同的实现,最终组合成一个复杂的对象。

这个模式尤其适合那些需要在多个步骤中配置或构造对象的场景,例如建造房子、配置计算机、制作汉堡🍔等。而且它可以让代码更加清晰灵活,因为你可以通过不同的建造者来实现对象的不同变体。

案例:汉堡制作

假设我们有一个汉堡店,他们提供定制汉堡🍔。顾客可以选择面包类型、肉类、蔬菜、酱料等。每个汉堡可以有不同的组合,因此我们使用建造者模式来简化这个复杂的对象创建过程。

建造者模式的核心角色

  1. Builder(建造者接口/抽象类):定义创建产品对象的各个步骤的接口。
  2. ConcreteBuilder(具体建造者):实现Builder接口,提供步骤的具体实现。
  3. Director(指挥者):负责调用建造步骤,指导建造过程。
  4. Product(产品):最终要创建的复杂对象。

代码实现:汉堡制作 🍔

内部类实现:

Step 1:产品类 Burger
// 产品类:Burger
public class Burger {private String bun;       // 面包private String patty;     // 肉饼private String sauce;     // 酱料private String vegetables; // 蔬菜// 私有化构造函数,防止外部直接实例化private Burger() {}// 内部静态Builder类public static class Builder {private String bun;private String patty;private String sauce;private String vegetables;// 构建面包类型public Builder setBun(String bun) {this.bun = bun;return this;}// 构建肉饼类型public Builder setPatty(String patty) {this.patty = patty;return this;}// 构建酱料类型public Builder setSauce(String sauce) {this.sauce = sauce;return this;}// 构建蔬菜种类public Builder setVegetables(String vegetables) {this.vegetables = vegetables;return this;}// 最终构建出一个完整的Burger对象public Burger build() {Burger burger = new Burger();burger.bun = this.bun;burger.patty = this.patty;burger.sauce = this.sauce;burger.vegetables = this.vegetables;return burger;}}// 打印出汉堡的详细信息@Overridepublic String toString() {return "Burger with " + bun + ", " + patty + ", " + sauce + ", " + vegetables;}
}
Step 2:指挥者 Director
// 指挥者:负责指导汉堡的制作过程
public class Chef {public Burger makeCheeseburger() {return new Burger.Builder().setBun("Sesame Bun")     // 芝麻面包.setPatty("Beef Patty")   // 牛肉饼.setSauce("Cheese Sauce") // 芝士酱.setVegetables("Lettuce") // 生菜.build();}public Burger makeVeganBurger() {return new Burger.Builder().setBun("Whole Grain Bun") // 全麦面包.setPatty("Vegan Patty")   // 素食饼.setSauce("Mustard Sauce") // 芥末酱.setVegetables("Tomato, Lettuce") // 番茄和生菜.build();}
}
Step 3:客户端代码
public class Main {public static void main(String[] args) {Chef chef = new Chef();// 制作一个芝士汉堡Burger cheeseburger = chef.makeCheeseburger();System.out.println(cheeseburger);// 制作一个素食汉堡Burger veganBurger = chef.makeVeganBurger();System.out.println(veganBurger);}
}
结果

当运行这段代码时,输出如下:

Burger with Sesame Bun, Beef Patty, Cheese Sauce, Lettuce
Burger with Whole Grain Bun, Vegan Patty, Mustard Sauce, Tomato, Lettuce
总结

🥷💻 在这个例子中,我们用建造者模式解决了汉堡制作的复杂性:

  1. 可扩展性:我们可以轻松地添加新步骤(比如加奶酪),或添加新的汉堡类型。
  2. 清晰性:使用链式调用方式构建对象,每一步都是明确的。
  3. 灵活性:不同的指挥者可以决定如何组合不同的步骤,产生不同的汉堡变种。

建造者模式非常适合处理需要多步骤配置的复杂对象创建需求,尤其是在需要灵活、可扩展的情况下。💡

抽象类实现

当你有多个复杂对象的构造方式类似,但是具体的构造细节不同,这时可以使用抽象类。抽象类提供一个统一的接口,并允许不同的具体实现类来实现各自的构建步骤。

例如,如果你有多个不同类型的“汉堡”或其他类型的复杂对象,这些对象有相似的结构,但具体的细节不同,那么抽象类就能发挥作用。抽象类提供了基础构建逻辑,而具体的子类负责实现细节

多个复杂对象共享部分构造逻辑:抽象类可以提供共享的构建步骤,具体的构建步骤由子类实现。

强制规范步骤:抽象类可以定义必须实现的方法,这样确保子类都能实现这些步骤。

减少重复代码:如果不同对象之间的构建步骤大部分相同,使用抽象类可以避免重复代码。

Step 1:产品类 Burger
// 产品类:汉堡
public class Burger {private String bun;private String patty;private String sauce;private String vegetables;// 各个字段的设置方法public void setBun(String bun) {this.bun = bun;}public void setPatty(String patty) {this.patty = patty;}public void setSauce(String sauce) {this.sauce = sauce;}public void setVegetables(String vegetables) {this.vegetables = vegetables;}// 输出汉堡详细信息@Overridepublic String toString() {return "Burger with " + bun + ", " + patty + ", " + sauce + ", " + vegetables;}
}
Step 2:抽象的 Builder 类
// 抽象建造者:定义基本的构建步骤
public abstract class BurgerBuilder {protected Burger burger;// 创建新的汉堡public void createNewBurger() {burger = new Burger();}// 具体的构建步骤,由子类实现public abstract void buildBun();public abstract void buildPatty();public abstract void buildSauce();public abstract void buildVegetables();// 返回最终构建的产品public Burger getBurger() {return burger;}
}
Step 3:具体的 Builder 类
// 具体的芝士汉堡建造者
public class CheeseburgerBuilder extends BurgerBuilder {@Overridepublic void buildBun() {burger.setBun("Sesame Bun");}@Overridepublic void buildPatty() {burger.setPatty("Beef Patty");}@Overridepublic void buildSauce() {burger.setSauce("Cheese Sauce");}@Overridepublic void buildVegetables() {burger.setVegetables("Lettuce");}
}// 具体的素食汉堡建造者
public class VeganBurgerBuilder extends BurgerBuilder {@Overridepublic void buildBun() {burger.setBun("Whole Grain Bun");}@Overridepublic void buildPatty() {burger.setPatty("Vegan Patty");}@Overridepublic void buildSauce() {burger.setSauce("Mustard Sauce");}@Overridepublic void buildVegetables() {burger.setVegetables("Tomato, Lettuce");}
}
Step 4:指挥者 Director
// 指挥者:负责调用建造者的构建步骤
public class Chef {private BurgerBuilder burgerBuilder;// 设置当前的建造者public void setBurgerBuilder(BurgerBuilder burgerBuilder) {this.burgerBuilder = burgerBuilder;}// 返回最终构建的汉堡public Burger getBurger() {return burgerBuilder.getBurger();}// 按步骤构建汉堡public void constructBurger() {burgerBuilder.createNewBurger();burgerBuilder.buildBun();burgerBuilder.buildPatty();burgerBuilder.buildSauce();burgerBuilder.buildVegetables();}
}
Step 5:客户端代码
public class Main {public static void main(String[] args) {Chef chef = new Chef();// 制作芝士汉堡BurgerBuilder cheeseburgerBuilder = new CheeseburgerBuilder();chef.setBurgerBuilder(cheeseburgerBuilder);chef.constructBurger();Burger cheeseburger = chef.getBurger();System.out.println(cheeseburger);// 制作素食汉堡BurgerBuilder veganBurgerBuilder = new VeganBurgerBuilder();chef.setBurgerBuilder(veganBurgerBuilder);chef.constructBurger();Burger veganBurger = chef.getBurger();System.out.println(veganBurger);}
}
输出结果
Burger with Sesame Bun, Beef Patty, Cheese Sauce, Lettuce
Burger with Whole Grain Bun, Vegan Patty, Mustard Sauce, Tomato, Lettuce
总结:使用抽象类的优点
  1. 扩展性更强:如果要添加新的汉堡种类(比如鸡肉汉堡),只需要继承抽象的 BurgerBuilder 类并实现它的具体方法,不需要修改已有的代码。
  2. 代码复用:公共逻辑可以在抽象类中实现,减少子类的代码重复。
  3. 更灵活的设计:通过定义抽象的步骤,强制每个子类实现各自的步骤,实现了结构的统一性和逻辑的灵活性。

💡 在这种情况下,抽象类为不同类型的汉堡提供了一个标准化的构建流程,同时允许具体的实现类定义各自的细节,使得代码更具灵活性和可维护性。

源码中的应用

Java 标准库中,建造者模式(Builder Pattern)被广泛应用于许多类库和框架,尤其是在创建复杂对象时。这个模式的使用可以大大提高代码的可读性、可维护性,并且能够简化对象的创建过程

以下是一些经典的 Java 源码应用了建造者模式的例子

1. StringBuilderStringBuffer

StringBuilderStringBuffer 是 Java 中经常使用的用于操作字符串的类,它们可以逐步构建一个字符串,类似于建造者模式。

StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World").append("!");System.out.println(sb.toString());  // 输出 "Hello World!"

2.java.util.stream.Stream.Builder

Java 8 引入了 Stream API,Stream.Builder 是一种典型的建造者模式的应用,用于构建 Stream 对象。

Stream.Builder<String> builder = Stream.builder();
builder.add("one").add("two").add("three");Stream<String> stream = builder.build();  // 创建流
stream.forEach(System.out::println);

3.Lombok 中的 @Builder 注解

示例:使用 @Builder 注解

假设我们有一个 Person 类,包含姓名、年龄和地址等字段。我们可以使用 @Builder 注解来简化对象创建。

import lombok.Builder;
import lombok.ToString;@Builder
@ToString
public class Person {private String name;private int age;private String address;
}

通过 @Builder 注解,Lombok 会自动为我们生成一个建造者模式类。接下来我们就可以像这样使用:

public class Main {public static void main(String[] args) {Person person = Person.builder().name("Alice").age(25).address("123 Main St").build();System.out.println(person);}
}

#####*Lombok 自动生成的代码

Lombok 的 @Builder 实际上为我们生成了一个内部的静态 Builder 类,它的结构与我们手动实现的建造者模式非常相似。以 Person 类为例,Lombok 生成的 Builder 类大概是这样:

public class Person {private String name;private int age;private String address;// 私有构造函数,防止直接创建对象private Person(PersonBuilder builder) {this.name = builder.name;this.age = builder.age;this.address = builder.address;}public static PersonBuilder builder() {return new PersonBuilder();}// 静态的内部类 PersonBuilderpublic static class PersonBuilder {private String name;private int age;private String address;public PersonBuilder name(String name) {this.name = name;return this;}public PersonBuilder age(int age) {this.age = age;return this;}public PersonBuilder address(String address) {this.address = address;return this;}public Person build() {return new Person(this);}}@Overridepublic String toString() {return "Person(name=" + this.name + ", age=" + this.age + ", address=" + this.address + ")";}
}

总结

这些 Java 标准库中的类展示了建造者模式在实际开发中的广泛应用。建造者模式通过分步骤地构建复杂对象,提高了代码的灵活性可读性,避免了冗长的构造函数调用。这使得代码更具扩展性,并且适合于那些对象创建过程中需要多步骤、多参数的场景。

相关文章:

Java实现建造者模式和源码中的应用

Java实现建造者模式&#xff08;Builder Pattern&#xff09; 文章目录 Java实现建造者模式&#xff08;Builder Pattern&#xff09;案例&#xff1a;汉堡制作建造者模式的核心角色代码实现&#xff1a;汉堡制作 &#x1f354;内部类实现&#xff1a;Step 1&#xff1a;产品类…...

Windows安装docker

Windows有两种虚拟号技术&#xff0c;WLS和Hyper-V&#xff0c;因为我的win10是家庭版&#xff0c;所以只能采用WLS来安装docker。 在Windows 10家庭版中&#xff0c;由于默认不包含Hyper-V功能&#xff0c;因此容器功能也不可用。即使启用了Hyper-V&#xff0c;由于Docker De…...

SprinBoot+Vue校园车辆管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…...

【C语言进阶】C语言动态内存管理:深入理解malloc、calloc与realloc

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C语言 “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C语言自定义类型 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀C语言动态内存管理 &#…...

Java+控制台 图书管理系统

Java控制台 图书管理系统 一、系统介绍二、功能展示1.用户登陆2.普通用户&#xff1a;图书查询、图书借阅、图书归还 、图书列表3.管理员:图书整理、图书添加、图书删除 四、其它1.其他系统实现 一、系统介绍 系统实现了普通用户&#xff1a;图书查询、图书借阅、图书归还 、图…...

gi清除无用缓存

使用 git pull --rebase 的确会对 Git 仓库的大小产生影响&#xff0c;主要是因为每次重新基于最新的代码进行 rebase&#xff0c;Git 会保存历史提交的变动。即使你的实际代码量不多&#xff0c;Git 依然需要存储所有这些历史变更记录&#xff0c;因此可能会导致仓库的大小逐渐…...

云PLM系统对企业影响有哪些?解析云PLM系统的作用

随着企业数字化转型的加速&#xff0c;云PLM产品生命周期管理系统逐渐成为企业提升竞争力、优化资源配置、加速产品上市的重要工具。云PLM系统通过云计算技术&#xff0c;不仅解决了传统PLM系统面临的高昂部署成本、复杂维护、数据共享效率低等问题&#xff0c;还为企业带来了更…...

四、查找算法

文章目录 一、查找算法介绍二、线性查找算法2.1 顺序查找2.2 二分查找&#xff08;折半查找&#xff09;2.3 插值查找2.4 斐波拉契&#xff08;黄金分割法&#xff09;查找算法 三、树表的查找3.1 二叉排序树3.1.1 引入3.1.2 基本介绍3.1.3 二叉树的遍历3.1.4 二叉树的删除 3.2…...

果蔬识别系统性能优化之路(三)

目录 前情提要遗留问题 解决方案优化查询速度优化ivf初始化的速度 下一步 前情提要 果蔬识别系统性能优化之路&#xff08;二&#xff09; 遗留问题 优化同步速度&#xff0c;目前大约30秒&#xff0c;不是一个生产速度 这次来解决遗留问题 通过console&#xff0c;发现两个…...

时序预测|基于小龙虾优化高斯过程GPR数据回归预测Matlab程序COA-GPR 多特征输入单输出 附赠基础GPR

时序预测|基于小龙虾优化高斯过程GPR数据回归预测Matlab程序COA-GPR 多特征输入单输出 附赠基础GPR 文章目录 一、基本原理二、实验结果三、核心代码四、代码获取五、总结 时序预测|基于小龙虾优化高斯过程GPR数据回归预测Matlab程序COA-GPR 多特征输入单输出 附赠基础GPR 一、…...

C#进阶-快速了解IOC控制反转及相关框架的使用

目录 一、了解IOC 1、概念 2、生命周期 二、IOC服务示例 1、定义服务接口 2、实现服务 三、扩展-CommunityToolkit.Mvvm工具包 Messenger信使 方式一&#xff08;收发消息&#xff09; 方式二&#xff08;收发消息&#xff09; 方式三&#xff08;请求消息&#xf…...

C++内存布局

文章目录 C内存布局1.文字介绍2.图片介绍3.代码介绍 C内存布局 1.文字介绍 1.内核态空间 2.用户态空间 (1)栈区&#xff1a;存储局部变量和函数调用的相关信息&#xff0c;栈的特点是自动分配和释放&#xff0c;由操作系统管理。栈由高地址向低地址生长&#xff0c;通常为0x…...

【Linux 19】线程概念

文章目录 &#x1f308; 一、线程的概念⭐ 1. 线程是什么⭐ 2. 线程的优点⭐ 3. 线程的缺点⭐ 4. 线程的异常⭐ 5. 线程的用途 &#x1f308; 二、进程和线程⭐ 1. 进程和线程的区别⭐ 2. 进程的多线程共享⭐ 3. 进程和线程的关系⭐ 3. 进程和线程的关系 &#x1f308; 一、线程…...

[区间dp]添加括号

题目描述 有一个 n n n 个元素的数组 a a a。不改变序列中每个元素在序列中的位置&#xff0c;把它们相加&#xff0c;并用括号记每次加法所得的和&#xff0c;称为中间和。现在要添上 n − 1 n - 1 n−1 对括号&#xff0c;加法运算依括号顺序进行&#xff0c;得到 n − …...

jenkins流水线+k8s部署springcloud微服务架构项目

文章目录 1.k8s安装2.jenkins安装3.k8s重要知识1.简介2.核心概念3.重要命令1.查看集群消息2.命名空间3.资源创建/更新4.资源查看5.描述某个资源的详细信息6.资源编辑7.资源删除8.资源重启9.查看资源日志10.资源标签 4.k8s控制台1.登录2.界面基本操作1.选择命名空间2.查看命名空…...

安卓开发板_联发科MTK开发评估套件串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发&#xff0c;USB 串口适配器&#xff08; USB 转串口 TTL 适配器的简称&#xff09;对于检查系统启动日志非常有用&#xff0c;特别是在没有图形桌面显示的情况下。 1.选购适配器 常用的许多 USB 转串口的适配器&#xf…...

vue+el-table 可输入表格使用上下键进行input框切换

使用上下键进行完工数量这一列的切换 <el-table :data"form.detailList" selection-change"handleChildSelection" ref"bChangeOrderChild" max-height"500"><!-- <el-table-column type"selection" width&quo…...

中国书法——孙溟㠭浅析碑帖《三希堂法帖》

孙溟㠭浅析碑帖《三希堂法帖》 全称是《三希堂石渠宝笈法帖》&#xff0c;是中国清代宫廷刻帖&#xff0c;一共三十二册。 清朝高宗弘历收藏了晋王羲之《快雪时晴帖》&#xff0c;王献之的《中秋帖》&#xff0c;王珣的《伯远帖》三种王氏原墨迹。故而把所藏法书之所…...

深入探讨生成对抗网络(GANs):颠覆传统的AI创作方式

在人工智能的快速发展中&#xff0c;生成对抗网络&#xff08;Generative Adversarial Networks, GANs&#xff09;无疑是一个引人注目的技术。自2014年由Ian Goodfellow等人首次提出以来&#xff0c;GANs已经在图像生成、文本生成、视频生成等多个领域展现出了惊人的能力。本文…...

vmware Vnet8虚拟网卡丢失的找回问题

vmware Vnet8虚拟网卡丢失的找回问题 1.打开VMware Workstation 2.然后点击Edit --> Virtual Network Edit --> 打开Virtual Network Edit框 &#xff0c; 3.点击最下面的的Restore Default 按钮&#xff0c; 3.恢复默认设置&#xff0c;这会在网络连接那块可以看到丢失…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...