通用Builder工具类
假设有一个Java实体类定义:
public class Request {private String type;private String op;private PageInfo pageInfo;public static class PageInfo {private Integer pageNum;private Integer pageSize;}// 省略getter和setter...
}
在代码中创建这个对象,需要写以下代码:
public static void main(String[] args) {// 创建PageInfoRequest.PageInfo pageInfo = new Request.PageInfo();pageInfo.setPageNum(1);pageInfo.setPageSize(10);// 创建RequestRequest request = new Request();request.setOp("op");request.setType("type");request.setPageInfo(pageInfo);// 使用request...
}
由于对象创建与对象初始化相互分离,以上代码看起来十分冗长,每个属性都需要一条setter语句来赋值,当属性数量较多时看起来非常不优雅。另外,由于嵌套类的存在,创建最外层对象之前,必须把所有内层对象先创建完毕,实在是恶心至极。
针对以上问题,熟悉设计模式的朋友应该很快就能想到使用Builder模式改写这个类:
public class Request {private String type;private String op;private PageInfo pageInfo;private Request(String type, String op, PageInfo pageInfo) {this.type = type;this.op = op;this.pageInfo = pageInfo;}// 省略getter和setter...public static RequestBuilder builder() {return new RequestBuilder();}public static class PageInfo {private Integer pageNum;private Integer pageSize;private PageInfo(Integer pageNum, Integer pageSize) {this.pageNum = pageNum;this.pageSize = pageSize;}// 省略getter和setter...public static PageInfoBuilder builder() {return new PageInfoBuilder();}public static class PageInfoBuilder {private Integer pageNum;private Integer pageSize;public PageInfoBuilder pageNum(Integer pageNum) {this.pageNum = pageNum;return this;}public PageInfoBuilder pageSize(Integer pageSize) {this.pageSize = pageSize;return this;}public PageInfo build() {return new PageInfo(this.pageNum, this.pageSize);}}}public static class RequestBuilder {private String type;private String op;private PageInfo pageInfo;public RequestBuilder type(String type) {this.type = type;return this;}public RequestBuilder op(String op) {this.op = op;return this;}public RequestBuilder pageInfo(PageInfo pageInfo) {this.pageInfo = pageInfo;return this;}public Request build() {return new Request(this.type, this.op, this.pageInfo);}}
}
这样就能使用流畅的链式调用创建对象,看起来行云流水:
public static void main(String[] args) {Request request = Request.builder().op("op").type("type").pageInfo(Request.PageInfo.builder().pageNum(1).pageSize(10).build()).build();// 使用request...
}
但是问题来了,假设Request这个对象是一个第三方框架或类库中的类,且并没有按照Builder模式来实现,由于无法修改该类的代码,我们也只能被迫使用setter方法来创建这个对象。在这种情况下,我们还能拥有像之前一样丝滑般的体验吗?
下面介绍一个简单的小技巧解决这个问题。
通用Builder工具类
public class BuilderUtils {public static <T> T build(T obj, Consumer<T> applyFunc) {applyFunc.accept(obj);return obj;}
}
上面的工具类有一个build方法,这个方法只是在一个指定的对象obj上调用了我们传入的一个任意操作函数applyFunc。有了这个方法,就能在任意对象上实现类似Builder模式的写法。
import static byx.test.BuilderUtils.build;public static void main(String[] args) {Request request = build(new Request(), r -> {r.setOp("op");r.setType("type");r.setPageInfo(build(new Request.PageInfo(), p -> {p.setPageNum(1);p.setPageSize(10);}));});// 使用request...
}
这个方法巧妙地将对象创建与对象初始化结合在了一起。实际上这种方法比Builder模式更灵活,因为build方法传入的lambda表达式中可以执行任意操作,而不仅仅是给对象属性赋值。我们可以在其中加入任意复杂的逻辑,比如根据某些条件为对象属性赋予不同的值,或者执行初始化逻辑等。更重要的是,所有操作都包含在一个语句中,而不会打散在数不清的setter调用中。
相关文章:
通用Builder工具类
假设有一个Java实体类定义: public class Request {private String type;private String op;private PageInfo pageInfo;public static class PageInfo {private Integer pageNum;private Integer pageSize;}// 省略getter和setter... }在代码中创建这个对象&#…...
开源免费的海报设计器vue-fabric-editor
vue-fabric-editor 是一个基于 Vue.js 和 Fabric.js 的创新前端富文本编辑器,它将传统的文本输入体验与图形设计元素相结合,为用户提供了全新的内容创作方式。 以下是关于 vue-fabric-editor 的详细介绍: 一、技术特点 框架结合:…...
【学习笔记】Day 4 - Day 5
一、进度概述 1、新机环境配置 2、《地震勘探原理》第一章 3、对 “DL-FWI 研究方向展望” 组会的一些想法 二、详情 1、新机环境配置 配置新机环境着实耗了较多时间,导致理论进度推进较慢。 2、《地震勘探原理》第一章学习笔记 相关笔记在另一篇…...
MySQL数据分析进阶(十四)保护数据库
※食用指南:文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记,笔记整理比较粗糙,主要目的自存为主,记录完整的学习过程。(图片超级多,慎看!) 【中字】SQL进阶教程 | 史上最易懂S…...
排序算法之堆排序
title: 堆排序 date: 2024-7-23 15:48:25 0800 categories: 排序算法 tags:排序算法堆排序 description: 堆排序(Heap Sort)是一种基于堆的排序算法,具有较高的效率和稳定性。 math: true 堆排序 堆排序(Heap Sort)是…...
Python中的NLP宝库:探索顶级库与工具
标题:Python中的NLP宝库:探索顶级库与工具 Python,作为人工智能和机器学习任务中的关键编程语言,为自然语言处理(NLP)提供了丰富的库和工具。这些库不仅功能强大,而且大多数都是开源的…...
springboot + springcloud + Google pubsub+ firebase
1.pom依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-gcp-starter</artifactId><version>1.2.6.RELEASE</version></dependency><dependency><groupId>org.springframe…...
时序数据库TDengine和QuestDB对比
QuestDB和TDengine都是高性能的时序数据库(Time Series Database, TSDB),但它们在设计、功能、适用场景以及性能表现上各有特色。 以下是对两者的详细对比: 一、设计与架构 QuestDB 是一个开源的高性能SQL时序数据库࿰…...
Neuralink的进展与马斯克的技术愿景——从脑机接口到AI融合的未来
引言 Neuralink,这个由埃隆马斯克(Elon Musk)创立的公司,一直是科技界的焦点。自从其发布以来,Neuralink的脑机接口技术便吸引了全球的目光。最近,马斯克再次向公众展示了Neuralink的突破性进展࿰…...
大数据技术——实战项目:广告数仓(第四部分)
目录 第7章 数据仓库环境准备 7.1 数据仓库运行环境 7.1.1 Hive环境搭建 7.1.2 Yarn环境配置 7.2 数据仓库开发环境 第8章 广告数仓ODS层 8.1 广告信息表 8.2 推广平台表 8.3 产品表 8.4 广告投放表 8.5 日志服务器列表 8.6 广告监测日志表 8.7 数据装载脚本 第7章…...
cmake+ninja交叉编译android下的静态库
文章目录 cmakeninja案例背景重新安装ninja编译通过 参考 想整理一个库的cmake工程,他用 cmakeninja 简单了解了一下,是可以不依赖Android studio编译的cmake的,搜到了一个cmakeninja,参考[1] 案例 参考[1]中的代码 背景 cm…...
Vue项目-Table添加Form表单校验
一、HTML <template><div class"taskInfo"><el-form:model"generateParams":rules"formRules"ref"formRef"class"taskInfoForm"label-width"100px"><ul class"taskInfoSearch"&g…...
【iOS】—— 事件传递链和响应者链总结
事件传递链和响应者链总结 1. 事件传递链:事件传递链:传递流程:总结第一响应者: 2. 响应者链响应者链传递流程总结响应者链流程 总结: 之前也学习过这个内容这次在复习的时候,就想着写一下总结:…...
【多线程】初识进程和线程
💐个人主页:初晴~ 📚相关专栏:多线程 / javaEE初阶 前言 在我们之前编写的所有代码,都只能用上一个核心。众所周知,现在大多数CPU都有多个核心,但此时,无论如法优化程序,…...
1DCNN-2DResNet并行故障诊断模型
往期精彩内容: Python-凯斯西储大学(CWRU)轴承数据解读与分类处理 Python轴承故障诊断入门教学-CSDN博客 Python轴承故障诊断 (13)基于故障信号特征提取的超强机器学习识别模型-CSDN博客 Python轴承故障诊断 (14)高创新故障识别模型-CSDN…...
Java设计模式(原型模式)
定义 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。 角色 Prototype(抽象原型角色) ConcretePrototype(具体原型角色) Client(客户端角色 优点 简化对象的创建过程,…...
C/C++ 知识点:typedef 关键字
文章目录 一、typedef 关键字1、 基本用法2、常见用法2.1、为基本数据类型定义别名2.2、为结构体或联合体定义别名2.3、为指针类型定义别名2.4、为复杂模板类型定义别名 3、注意事项4、总结 前言: 在C(以及C语言)中,typedef 关键字…...
【Linux学习】进程间通信之 匿名管道 与 基于管道的进程池
🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 🍑进程间通信🐬进程间通信目的 📚管道 📕管道的原理🐧用fork来共享管道原…...
小团队如何选需求管理软件?8款顶级推荐
本文将分享8款适合小团队的需求管理软件:PingCode、Worktile、Tapd、Teambition、禅道、Asana、Jama Connect、Aha!。 在小团队中管理需求时,寻找合适的软件工具常常让人头疼,不同的需求管理软件提供各种功能,但哪些功能真正适合…...
docker操作入门
1.创建镜像,使用当前文件 docker build -t experience . 2.运行容器 docker run -d -p 8501:8501 --name my-running-app my-python-api docker run -p 8508:8508 experience docker run -p 8508:8508 -p 8509:8509 experience 3.查看容器状态 docker ps docker p…...
手把手教你用PasteMD:无需代码,让AI自动整理会议纪要和笔记
手把手教你用PasteMD:无需代码,让AI自动整理会议纪要和笔记 1. 为什么你需要PasteMD 1.1 信息整理的痛点 在日常工作中,我们经常遇到这样的场景: 会议结束后,笔记上全是零散的关键词和箭头从网页复制的内容粘贴后格…...
灵感画廊实际作品:基于‘纪实瞬间’预设的城市街景写实图像生成
灵感画廊实际作品:基于‘纪实瞬间’预设的城市街景写实图像生成 “见微知著,凝光成影。将梦境的碎片,凝结为永恒的视觉诗篇。” 今天,我们不谈复杂的参数,也不讲枯燥的部署。我想带你走进一个特别的创作空间——灵感画…...
SEO_如何通过内容优化有效提升SEO效果?(403 )
如何通过内容优化有效提升SEO效果? 在当今竞争激烈的网络环境中,如何通过内容优化有效提升SEO效果,成为了每一个网站运营者的关键问题。搜索引擎优化(SEO)是一门艺术,需要我们在内容策略和技术手段上不断探…...
从零到一:基于XXL-JOB构建企业级分布式任务调度中心实战指南
1. 为什么选择XXL-JOB作为分布式任务调度方案 第一次接触分布式任务调度时,我像大多数开发者一样面临选择困难。市面上既有成熟的商业产品,也有各种开源方案。经过多个项目的实战验证,XXL-JOB以其轻量级架构和易用性脱颖而出。这个由国内开发…...
嵌入式Linux按键驱动:除了轮询,你更应该掌握的3种高效方式(poll/中断/异步通知实战)
嵌入式Linux按键驱动开发:超越轮询的三种高效方案实战解析 在资源受限的嵌入式设备中,物理按键的处理往往成为影响系统响应速度和功耗的关键因素。传统轮询方式虽然实现简单,但在智能家居面板、手持设备等场景下,其CPU占用率高、响…...
AI 为什么不认识 Excel 文件?——用 SpreadJS 与 GCExcel 打通 AI 与数据的鸿沟
在技术领域,我们常常被那些闪耀的、可见的成果所吸引。今天,这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力,让我们得以一窥未来的轮廓。然而,作为在企业一线构建、部署和维护复杂系统的实践者,我们深知…...
2025届毕业生推荐的十大降AI率神器实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在当下的学术写作情形里,论文AI网站主要是提供文献检索、提纲生成、段落润色以及…...
[具身智能-237]:OpenCV - 图像的坐标轴
OpenCV 的图像坐标系与我们在数学课上学到的标准笛卡尔坐标系有显著不同,这是初学者最容易混淆的地方。简单来说,它的核心规则是:原点在左上角,X 轴向右,Y 轴向下。下面为你详细拆解这个坐标系的构成,以及在…...
从春招到Offer:一位应届生的多益网络软件开发求职全记录
1. 春招末班车:从"破罐破摔"到投出第一份简历 五月的广州已经热得让人喘不过气,我的求职焦虑却比天气更让人窒息。看着身边同学一个个晒出offer,我才惊觉自己错过了整个金三银四。毕设和论文像两座大山,把求职计划硬生生…...
【26大英赛】全国大学生英语竞赛高频核心词汇表pdf电子版(考前必背单词)
2026年全国大学生英语竞赛进入最后冲刺阶段,考试日期定于4月12日。距离考试仅剩6天时间,备考工作刻不容缓。 为助力考生高效复习,现推出最新版竞赛核心词汇手册。该资料以PDF电子版形式提供,支持自由下载和打印使用,方…...
